diff --git a/demos/_includes/FakerPersistence.php b/demos/_includes/FakerPersistence.php index a455bc5f5a..5fc50824f9 100644 --- a/demos/_includes/FakerPersistence.php +++ b/demos/_includes/FakerPersistence.php @@ -22,6 +22,9 @@ public function __construct() $this->faker = FakerFactory::create(); } + /** + * @return \Traversable> + */ public function prepareIterator(Model $model): \Traversable { foreach ($this->export($model) as $row) { @@ -29,6 +32,11 @@ public function prepareIterator(Model $model): \Traversable } } + /** + * @param list $fields + * + * @return list> + */ private function export(Model $model, array $fields = []): array { if (!$fields) { diff --git a/demos/_includes/FlyersForm.php b/demos/_includes/FlyersForm.php index 323fd7462d..96add3c018 100644 --- a/demos/_includes/FlyersForm.php +++ b/demos/_includes/FlyersForm.php @@ -10,8 +10,10 @@ class FlyersForm extends Form { + /** @var array> */ public array $flyers = []; + /** @var list> */ public array $cards = [ ['name' => 'Frequent Flyer Program', 'id' => 1, 'nodes' => []], ['name' => 'World Class', 'id' => 2, 'nodes' => []], diff --git a/demos/collection/multitable.php b/demos/collection/multitable.php index f0cc53ce75..3a74e71d8d 100644 --- a/demos/collection/multitable.php +++ b/demos/collection/multitable.php @@ -21,8 +21,6 @@ // re-usable component implementing counter $finderClass = AnonymousClassNameCache::get_class(fn () => new class extends Columns { - public array $route = []; - /** * @return list */ @@ -36,6 +34,9 @@ private function explodeSelectionValue(string $value): array return $res; } + /** + * @param list $route + */ #[\Override] public function setModel(Model $model, array $route = []): void { diff --git a/demos/data-action/factory-view.php b/demos/data-action/factory-view.php index 2d19d01955..5419b5f94e 100644 --- a/demos/data-action/factory-view.php +++ b/demos/data-action/factory-view.php @@ -23,6 +23,7 @@ $myFactory = AnonymousClassNameCache::get_class(fn () => new class extends ExecutorFactory { public $buttonPrimaryColor = 'green'; + /** @var array */ protected array $actionIcon = [ 'callback' => 'sync', 'preview' => 'eye', @@ -43,7 +44,7 @@ public function __construct() } /** - * @return array + * @return array */ protected function getCardButton(Model\UserAction $action) { diff --git a/demos/interactive/popup.php b/demos/interactive/popup.php index 953ea4a679..496e11f15b 100644 --- a/demos/interactive/popup.php +++ b/demos/interactive/popup.php @@ -35,6 +35,7 @@ $cartClass = AnonymousClassNameCache::get_class(fn () => new class extends Lister { use SessionTrait; + /** @var array */ public array $items = []; public $defaultTemplate = 'lister.html'; @@ -87,8 +88,6 @@ public function removeItem($index): void #[\Override] protected function renderView(): void { - // memorize items - $this->setSource($this->items); parent::renderView(); diff --git a/phpstan.neon.dist b/phpstan.neon.dist index c18809e57d..cd380564ef 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -11,8 +11,6 @@ parameters: - js ignoreErrors: - - '~^(Property .+ has|Method .+\(\) (has parameter \$.+ with|return type has)) no value type specified in iterable type .+\.$~' - # relax strict rules - '~^Only booleans are allowed in .+, .+ given( on the (left|right) side)?\.$~' - '~^Variable (static )?(property access|method call) on .+\.$~' @@ -374,6 +372,13 @@ parameters: message: '~^Call to an undefined method Atk4\\Ui\\Js\\JsChain::addJsonData\(\)\.$~' count: 1 + # TODO fix once PHP 7.4 support is dropped + - + path: 'src/Console.php' + identifier: missingType.parameter + message: '~^Method Atk4\\Ui\\Console::\w+\(\) has parameter \$message with no type specified\.$~' + count: 9 + # TODO fix contravariance for View::set() method - path: 'src/Console.php' @@ -395,6 +400,11 @@ parameters: identifier: method.childParameterType message: '~^Parameter #1 \$fx \(Closure\(Atk4\\Ui\\Js\\Jquery, mixed, mixed, mixed, mixed, mixed, mixed, mixed, mixed, mixed, mixed\): \(Atk4\\Ui\\Js\\JsExpressionable\|Atk4\\Ui\\View\|string\|void\)\) of method Atk4\\Ui\\JsCallback::set\(\) should be contravariant with parameter \$fx \(Closure\(mixed, mixed, mixed, mixed, mixed, mixed, mixed, mixed, mixed, mixed\): mixed\) of method Atk4\\Ui\\Callback::set\(\)$~' count: 1 + - + path: 'src/JsCallback.php' + identifier: method.childParameterType + message: '~^Parameter #2 \$args \(array\) of method Atk4\\Ui\\JsCallback::set\(\) should be contravariant with parameter \$fxArgs \(list\) of method Atk4\\Ui\\Callback::set\(\)$~' + count: 1 - path: 'src/Loader.php' identifier: method.childParameterType @@ -606,7 +616,7 @@ parameters: - path: 'src/Wizard.php' identifier: assign.propertyType - message: '~^Property Atk4\\Ui\\Wizard::\$steps \(array\) does not accept array\.$~' + message: '~^Property Atk4\\Ui\\Wizard::\$steps \(list\) does not accept non-empty-list\.$~' count: 1 # TODO these rules are generated, this ignores should be fixed in the code diff --git a/src/AbstractView.php b/src/AbstractView.php index d84ef4cecf..1303634cd0 100644 --- a/src/AbstractView.php +++ b/src/AbstractView.php @@ -37,7 +37,7 @@ abstract class AbstractView * initialized by calling init() or adding into App or another initialized View, * then add() will be re-invoked with the contents of this array. * - * @var array|null + * @var list}>|null */ protected ?array $_addLater = []; @@ -65,6 +65,8 @@ protected function init(): void } /** + * @param array $args + * * @return ($object is View ? View : self) */ public function add(self $object, array $args = []): self diff --git a/src/Accordion.php b/src/Accordion.php index 78549e94c8..8ef55ef6f5 100644 --- a/src/Accordion.php +++ b/src/Accordion.php @@ -19,13 +19,13 @@ class Accordion extends View public $ui = 'accordion'; - /** @var array|string|null The CSS class for Fomantic-UI accordion type. */ + /** @var list|string|null The CSS class for Fomantic-UI accordion type. */ public $type; - /** @var array Settings as per Fomantic-UI accordion settings. */ + /** @var array Settings as per Fomantic-UI accordion settings. */ public $settings = []; - /** @var array A collection of AccordionSection in this Accordion. */ + /** @var list A collection of AccordionSection in this Accordion. */ public $sections = []; /** @var int The AccordionSection index number to activate on load. */ @@ -116,8 +116,9 @@ public function jsToggle($section, $when = false): JsExpressionable * Ex: toggle an accordion from it's index value. * $accordion->jsBehavior('toggle', 1). * - * @param string $behavior the name of the behavior for the module - * @param bool $when + * @param string $behavior the name of the behavior for the module + * @param list $args + * @param bool $when * * @return JsChain */ diff --git a/src/App.php b/src/App.php index 9eb0e44bc7..811d41163b 100644 --- a/src/App.php +++ b/src/App.php @@ -49,8 +49,8 @@ class App private static ?string $shutdownReservedMemory; // @phpstan-ignore property.onlyRead private static ?int $errorReportingLevel = null; - /** @var array|false Location where to load JS/CSS files */ - public $cdn = [ + /** @var array Location where to load JS/CSS files */ + public array $cdn = [ 'atk' => '/public', 'jquery' => '/public/external/jquery/dist', 'fomantic-ui' => '/public/external/fomantic-ui/dist', @@ -75,7 +75,7 @@ class App /** @var Layout the top-most view object */ public $layout; - /** @var string|array Set one or more directories where templates should reside. */ + /** @var string|list Set one or more directories where templates should reside. */ public $templateDir; /** @var bool Will replace an exception handler with our own, that will output errors nicely. */ @@ -140,6 +140,9 @@ class App /** @var class-string */ public $templateClass = HtmlTemplate::class; + /** + * @param array $defaults + */ public function __construct(array $defaults = []) { if (isset($defaults['request'])) { @@ -508,7 +511,7 @@ public function setResponseHeader(string $name, string $value): self * directly, instead call it from Callback, JsCallback or similar * other classes. * - * @param string|StreamInterface|array $output Array type is supported only for JSON response + * @param string|StreamInterface|array $output Array type is supported only for JSON response * * @return never */ @@ -539,7 +542,7 @@ public function terminate($output = ''): void } /** - * @param string|array|View|HtmlTemplate $output + * @param string|array|View|HtmlTemplate $output * * @return never */ @@ -556,7 +559,7 @@ public function terminateHtml($output): void } /** - * @param string|array|View $output + * @param string|array|View $output * * @return never */ @@ -573,7 +576,7 @@ public function terminateJson($output): void /** * Initializes layout. * - * @param Layout|array $seed + * @param Layout|array $seed * * @return $this */ @@ -643,8 +646,8 @@ public function addStyle($style): void /** * Add a new object into the app. You will need to have Layout first. * - * @param AbstractView $object - * @param string|array|null $region + * @param AbstractView $object + * @param string|array|null $region * * @return ($object is View ? View : AbstractView) */ @@ -973,7 +976,7 @@ public function isVoidTag(string $tag): bool * --> welcome' * * @param array<0|string, string|bool> $attr - * @param string|array, 2?: string|array|null}|string>|null $value + * @param string|list, 2?: string|list|null}|string>|null $value */ public function getTag(string $tag, array $attr = [], $value = null): string { @@ -1247,7 +1250,7 @@ private function outputResponseHtml(string $data): void } /** - * @param string|array $data + * @param string|array $data */ private function outputResponseJson($data): void { diff --git a/src/App/SessionManager.php b/src/App/SessionManager.php index a748ad5fd0..c77b06be8c 100644 --- a/src/App/SessionManager.php +++ b/src/App/SessionManager.php @@ -24,6 +24,9 @@ protected function isSessionActive(): bool return $status === \PHP_SESSION_ACTIVE; } + /** + * @return array + */ protected function createStartSessionOptions(): array { return []; diff --git a/src/Behat/Context.php b/src/Behat/Context.php index 4f60b2bcad..624d0af80f 100644 --- a/src/Behat/Context.php +++ b/src/Behat/Context.php @@ -101,6 +101,8 @@ protected function getFinishedScript(): string /** * Wait till jQuery AJAX request finished and no animation is perform. + * + * @param list $args */ protected function jqueryWait(string $extraWaitCondition = 'true', array $args = [], int $maxWaitdurationMs = 5000): void { diff --git a/src/Behat/MinkSession.php b/src/Behat/MinkSession.php index c55b8eb6fe..704756a36d 100644 --- a/src/Behat/MinkSession.php +++ b/src/Behat/MinkSession.php @@ -25,18 +25,27 @@ public function getDriver(): MinkSeleniumDriver return parent::getDriver(); // @phpstan-ignore return.type } + /** + * @param list $args + */ #[\Override] public function executeScript($script, array $args = []): void { $this->getDriver()->executeScript($script, $args); } + /** + * @param list $args + */ #[\Override] public function evaluateScript($script, array $args = []) { return $this->getDriver()->evaluateScript($script, $args); } + /** + * @param list $args + */ #[\Override] public function wait($time, $condition = 'false', array $args = []) { diff --git a/src/Behat/RwDemosContextTrait.php b/src/Behat/RwDemosContextTrait.php index 825a99d7e2..5781e87412 100644 --- a/src/Behat/RwDemosContextTrait.php +++ b/src/Behat/RwDemosContextTrait.php @@ -30,7 +30,7 @@ trait RwDemosContextTrait /** @var array|null */ protected ?array $databaseBackupModels = null; - /** @var array>>|null */ + /** @var array>>|null */ protected ?array $databaseBackupData = null; protected function getDemosDb(): Persistence\Sql diff --git a/src/Breadcrumb.php b/src/Breadcrumb.php index 902e51d57e..b7e54c154b 100644 --- a/src/Breadcrumb.php +++ b/src/Breadcrumb.php @@ -10,7 +10,7 @@ class Breadcrumb extends Lister public $defaultTemplate = 'breadcrumb.html'; - /** @var array */ + /** @var list}> */ public $path = []; /** @var string */ @@ -51,8 +51,8 @@ public function popTitle() /** * Adds a new link that will appear on the left. * - * @param string $section Title of link - * @param string|array $link Link itself + * @param string $section Title of link + * @param string|array<0|string, string|int|false> $link Link itself * * @return $this */ diff --git a/src/Button.php b/src/Button.php index 4365f03719..68e9e18439 100644 --- a/src/Button.php +++ b/src/Button.php @@ -13,10 +13,10 @@ class Button extends View public $ui = 'button'; - /** @var string|array|Icon Icon that will appear on the button (left). */ + /** @var string|array<0|string, mixed>|Icon Icon that will appear on the button (left). */ public $icon; - /** @var string|array|Icon Additional icon that can appear on the right of the button. */ + /** @var string|array<0|string, mixed>|Icon Additional icon that can appear on the right of the button. */ public $iconRight; #[\Override] diff --git a/src/Callback.php b/src/Callback.php index fe94f7ddf3..82f3d06952 100644 --- a/src/Callback.php +++ b/src/Callback.php @@ -67,7 +67,7 @@ public function getUrlTrigger(): string * @template T * * @param \Closure(mixed, mixed, mixed, mixed, mixed, mixed, mixed, mixed, mixed, mixed): T $fx - * @param array $fxArgs + * @param list $fxArgs * * @return T|null */ @@ -146,6 +146,8 @@ public function getUrl(string $value = 'callback'): string /** * Return proper URL argument for this callback. + * + * @return array */ private function getUrlArguments(?string $value = null): array { diff --git a/src/Card.php b/src/Card.php index ac5f6f1e6c..1912ad1be6 100644 --- a/src/Card.php +++ b/src/Card.php @@ -48,7 +48,7 @@ class Card extends View /** @var CardSection|null The main card section of this card */ public $section; - /** @var array The CardSection default seed. */ + /** @var array The CardSection default seed. */ public $cardSectionSeed = [CardSection::class]; /** @var View|null The extra content view container for the card. */ @@ -57,7 +57,7 @@ class Card extends View /** @var string|View|null A description inside the Card content. */ public $description; - /** @var array|Button|null */ + /** @var array|Button|null */ public $buttons; /** @var bool How buttons are display inside button container */ @@ -166,7 +166,7 @@ public function addContent(View $view) } /** - * @param array|null $fields + * @param list|null $fields */ #[\Override] public function setModel(Model $entity, ?array $fields = null): void @@ -188,6 +188,8 @@ public function setModel(Model $entity, ?array $fields = null): void /** * Add a CardSection to this card. * + * @param list $fields + * * @return View */ public function addSection(?string $title = null, ?Model $entity = null, ?array $fields = null, bool $useTable = false, bool $useLabel = false) @@ -208,6 +210,8 @@ public function addSection(?string $title = null, ?Model $entity = null, ?array /** * Execute Model user action via button in Card. * + * @param array $args + * * @return $this */ public function addClickAction(Model\UserAction $action, ?Button $button = null, array $args = [], ?string $confirm = null): self @@ -258,6 +262,8 @@ public function addClickAction(Model\UserAction $action, ?Button $button = null, /** * Set extra content using model field. + * + * @param list $fields */ public function addExtraFields(Model $entity, array $fields, ?string $glue = null): void { @@ -320,7 +326,7 @@ public function addImage($img) /** * Add button to card. * - * @param Button|array $seed + * @param Button|array $seed * * @return View */ diff --git a/src/CardDeck.php b/src/CardDeck.php index 5eff8682ce..24cbdf80c4 100644 --- a/src/CardDeck.php +++ b/src/CardDeck.php @@ -22,7 +22,7 @@ class CardDeck extends View public $defaultTemplate = 'card-deck.html'; - /** @var array Seed of Card inside this deck. */ + /** @var array Seed of Card inside this deck. */ public $cardSeed = [Card::class]; /** @var bool Whether card should use table display or not. */ @@ -52,19 +52,19 @@ class CardDeck extends View /** @var int The number of cards to be displayed per page. */ public $ipp = 9; - /** @var Menu|array|false Will be initialized to Menu object, however you can set this to false to disable menu. */ + /** @var Menu|array|false Will be initialized to Menu object, however you can set this to false to disable menu. */ public $menu; - /** @var array|VueComponent\ItemSearch|false */ + /** @var array|VueComponent\ItemSearch|false */ public $search = [VueComponent\ItemSearch::class]; - /** @var array Default notifier to perform when model action is successful * */ + /** @var array Default notifier to perform when model action is successful * */ public $notifyDefault = [JsToast::class]; - /** Model single scope action to include in table action column. Will include all single scope actions if empty. */ + /** @var list Model single scope action to include in table action column. Will include all single scope actions if empty. */ public array $singleScopeActions = []; - /** Model no_record scope action to include in menu. Will include all no record scope actions if empty. */ + /** @var list Model no_record scope action to include in menu. Will include all no record scope actions if empty. */ public array $noRecordScopeActions = []; /** @var string Message to display when record is add or edit successfully. */ @@ -76,7 +76,7 @@ class CardDeck extends View /** @var string Generic display message for no record scope action where model is not loaded. */ public $defaultMsg = 'Done!'; - /** @var array seed to create View for displaying when search result is empty. */ + /** @var array seed to create View for displaying when search result is empty. */ public $noRecordDisplay = [ Message::class, 'content' => 'Result empty!', @@ -84,7 +84,7 @@ class CardDeck extends View 'text' => 'Your search did not return any record or there is no record available.', ]; - /** @var array A collection of menu button added in Menu. */ + /** @var array A collection of menu button added in Menu. */ private $menuActions = []; /** @var string|null The current search query string. */ @@ -131,7 +131,8 @@ protected function addPaginator(): void } /** - * @param array|null $fields + * @param list $fields + * @param list $extra */ #[\Override] public function setModel(Model $model, ?array $fields = null, ?array $extra = null): void @@ -276,13 +277,21 @@ private function getReloadArgs() /** * Return proper action need to setup menu or action column. + * + * @return array */ private function getModelActions(string $appliesTo): array { if ($appliesTo === Model\UserAction::APPLIES_TO_SINGLE_RECORD && $this->singleScopeActions !== []) { - $actions = array_map(fn ($v) => $this->model->getUserAction($v), $this->singleScopeActions); + $actions = array_combine( + $this->singleScopeActions, + array_map(fn ($v) => $this->model->getUserAction($v), $this->singleScopeActions) + ); } elseif ($appliesTo === Model\UserAction::APPLIES_TO_NO_RECORDS && $this->noRecordScopeActions !== []) { - $actions = array_map(fn ($v) => $this->model->getUserAction($v), $this->noRecordScopeActions); + $actions = array_combine( + $this->noRecordScopeActions, + array_map(fn ($v) => $this->model->getUserAction($v), $this->noRecordScopeActions) + ); } else { $actions = $this->model->getUserActions($appliesTo); } diff --git a/src/CardSection.php b/src/CardSection.php index 7447edbee9..0044da45a8 100644 --- a/src/CardSection.php +++ b/src/CardSection.php @@ -19,7 +19,7 @@ class CardSection extends View /** @var string */ public $glue = ': '; - /** @var array */ + /** @var list */ public $tableClass = ['fixed', 'small']; #[\Override] @@ -31,7 +31,7 @@ protected function init(): void } #[\Override] - public function setModel(Model $entity, ?array $fields = null): void + public function setModel(Model $entity): void { $entity->assertIsEntity(); @@ -60,6 +60,8 @@ public function addDescription($description) /** * Add Model fields to a card section. + * + * @param list $fields */ public function addFields(Model $entity, array $fields, bool $useLabel = false, bool $useTable = false): void { @@ -74,6 +76,8 @@ public function addFields(Model $entity, array $fields, bool $useLabel = false, /** * Add fields label and value to section. + * + * @param list $fields */ private function addSectionFields(Model $entity, array $fields, bool $useLabel = false): void { @@ -96,6 +100,8 @@ private function addSectionFields(Model $entity, array $fields, bool $useLabel = /** * Add field into section using a CardTable View. + * + * @param list $fields */ private function addTableSection(Model $entity, array $fields): void { diff --git a/src/CardTable.php b/src/CardTable.php index c5e3a5d49f..8ecd2309cf 100644 --- a/src/CardTable.php +++ b/src/CardTable.php @@ -19,7 +19,7 @@ class CardTable extends Table protected bool $_bypass = false; /** - * @param array|null $fields + * @param list|null $fields */ #[\Override] public function setModel(Model $entity, ?array $fields = null): void diff --git a/src/Columns.php b/src/Columns.php index 9cb6b599e2..b4be3861cc 100644 --- a/src/Columns.php +++ b/src/Columns.php @@ -22,7 +22,7 @@ class Columns extends View /** @var int|false Sum of all column widths added so far. */ protected $calculatedWidth = 0; - /** @var array */ + /** @var array */ protected $cssWideClasses = [ 1 => 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten', 'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen', 'sixteen', @@ -31,7 +31,7 @@ class Columns extends View /** * Add new vertical column. * - * @param int|array $defaults specify width (1..16) or relative to $width + * @param int|array $defaults specify width (1..16) or relative to $width * * @return View */ diff --git a/src/Console.php b/src/Console.php index 80f1dd0e02..c7619778c8 100644 --- a/src/Console.php +++ b/src/Console.php @@ -114,7 +114,7 @@ public function set($fx = null, $event = null) try { $fx($this); } catch (\Throwable $e) { - $this->outputHtmlWithoutPre('
{0}
', [$this->getApp()->renderExceptionHtml($e)]); + $this->outputHtmlWithoutPre('
{ex}
', ['ex' => $this->getApp()->renderExceptionHtml($e)]); } } finally { $this->sseInProgress = false; @@ -174,6 +174,8 @@ private function escapeOutputHtml(string $message): string /** * Output a single line to the console. * + * @param array $context + * * @return $this */ public function output(string $message, array $context = []) @@ -186,6 +188,8 @@ public function output(string $message, array $context = []) /** * Output unescaped HTML to the console. * + * @param array $context + * * @return $this */ public function outputHtml(string $messageHtml, array $context = []) @@ -198,6 +202,8 @@ public function outputHtml(string $messageHtml, array $context = []) /** * Output unescaped HTML to the console without wrapping in
.
      *
+     * @param array $context
+     *
      * @return $this
      */
     protected function outputHtmlWithoutPre(string $messageHtml, array $context = [])
@@ -257,6 +263,8 @@ public function send(JsExpressionable $js)
      * Example: $console->exec('ping', ['-c', '5', '8.8.8.8']);
      *
      * All arguments are escaped.
+     *
+     * @param list $args
      */
     public function exec(string $command, array $args = []): ?bool
     {
@@ -264,7 +272,7 @@ public function exec(string $command, array $args = []): ?bool
             $this->set(function () use ($command, $args) {
                 $this->output(
                     '--[ Executing ' . $command
-                    . ($args ? ' with ' . count($args) . ' arguments' : '')
+                    . ($args !== [] ? ' with ' . count($args) . ' arguments' : '')
                     . ' ]--------------'
                 );
 
@@ -281,7 +289,7 @@ public function exec(string $command, array $args = []): ?bool
         stream_set_blocking($pipes[1], false);
         stream_set_blocking($pipes[2], false);
         // $pipes contain streams that are still open and not EOF
-        while ($pipes) {
+        while ($pipes) { // @TODO this condition is always true
             $read = $pipes;
             $j1 = null;
             $j2 = null;
@@ -319,7 +327,9 @@ public function exec(string $command, array $args = []): ?bool
     }
 
     /**
-     * @return array{resource, non-empty-array}
+     * @param list $args
+     *
+     * @return array{resource, non-empty-array}
      */
     protected function execRaw(string $command, array $args = [])
     {
@@ -359,6 +369,7 @@ protected function execRaw(string $command, array $args = [])
      * to pass on the property.
      *
      * @param object|class-string $object
+     * @param list         $args
      *
      * @return $this
      */
diff --git a/src/Crud.php b/src/Crud.php
index 0373e8de85..05bb693cac 100644
--- a/src/Crud.php
+++ b/src/Crud.php
@@ -17,28 +17,28 @@
 
 class Crud extends Grid
 {
-    /** @var array of fields to display in Grid */
+    /** @var list Fields to display in Grid */
     public $displayFields;
 
-    /** @var array|null of fields to edit in Form for Model edit action */
+    /** @var list|null Fields to edit in Form for Model edit action */
     public $editFields;
 
-    /** @var array|null of fields to edit in Form for Model add action */
+    /** @var list|null Fields to edit in Form for Model add action */
     public $addFields;
 
-    /** @var array Default notifier to perform when adding or editing is successful * */
+    /** @var array Default notifier to perform when adding or editing is successful * */
     public $notifyDefault = [JsToast::class];
 
-    /** @var bool|null should we use table column drop-down menu to display user actions? */
+    /** @var bool|null Should we use table column drop-down menu to display user actions? */
     public $useMenuActions;
 
     /** @var array Collection of APPLIES_TO_NO_RECORDS Scope Model action menu item */
     private array $menuItems = [];
 
-    /** Model single scope action to include in table action column. Will include all single scope actions if empty. */
+    /** @var list Model single scope action to include in table action column. Will include all single scope actions if empty. */
     public array $singleScopeActions = [];
 
-    /** Model no_record scope action to include in menu. Will include all no record scope actions if empty. */
+    /** @var list Model no_record scope action to include in menu. Will include all no record scope actions if empty. */
     public array $noRecordScopeActions = [];
 
     /** @var string Message to display when record is add or edit successfully. */
@@ -50,10 +50,10 @@ class Crud extends Grid
     /** @var string Generic display message for no record scope action where model is not loaded. */
     public $defaultMsg = 'Done!';
 
-    /** @var array> Callback containers for model action. */
+    /** @var list> Callback containers for model action. */
     public $onActions = [];
 
-    /** @var mixed recently deleted record ID. */
+    /** @var mixed Recently deleted record ID. */
     private $deletedId;
 
     #[\Override]
@@ -282,13 +282,21 @@ private function _getReloadArgs()
 
     /**
      * Return proper action need to setup menu or action column.
+     *
+     * @return array
      */
     private function _getModelActions(string $appliesTo): array
     {
         if ($appliesTo === Model\UserAction::APPLIES_TO_SINGLE_RECORD && $this->singleScopeActions !== []) {
-            $actions = array_map(fn ($v) => $this->model->getUserAction($v), $this->singleScopeActions);
+            $actions = array_combine(
+                $this->singleScopeActions,
+                array_map(fn ($v) => $this->model->getUserAction($v), $this->singleScopeActions)
+            );
         } elseif ($appliesTo === Model\UserAction::APPLIES_TO_NO_RECORDS && $this->noRecordScopeActions !== []) {
-            $actions = array_map(fn ($v) => $this->model->getUserAction($v), $this->noRecordScopeActions);
+            $actions = array_combine(
+                $this->noRecordScopeActions,
+                array_map(fn ($v) => $this->model->getUserAction($v), $this->noRecordScopeActions)
+            );
         } else {
             $actions = $this->model->getUserActions($appliesTo);
         }
diff --git a/src/Dropdown.php b/src/Dropdown.php
index 51cd3e7db8..cb7755efb2 100644
--- a/src/Dropdown.php
+++ b/src/Dropdown.php
@@ -18,7 +18,7 @@ class Dropdown extends Lister
     /** @var JsCallback|null Callback when a new value is selected in Dropdown. */
     public $cb;
 
-    /** @var array As per Fomantic-UI dropdown options. */
+    /** @var array As per Fomantic-UI dropdown options. */
     public $dropdownOptions = [];
 
     #[\Override]
diff --git a/src/Form.php b/src/Form.php
index b2792197df..84c1128eb9 100644
--- a/src/Form.php
+++ b/src/Form.php
@@ -61,7 +61,7 @@ class Form extends View
      * Will point to the Save button. If you don't want to have save button, then set this to false
      * or destroy it. Initialized by initLayout().
      *
-     * @var Button|array|false Button object, seed or false to not show button at all
+     * @var Button|array|false Button object, seed or false to not show button at all
      */
     public $buttonSave = [Button::class, 'Save', 'class.primary' => true];
 
@@ -96,6 +96,8 @@ class Form extends View
      *  Show "target' if 'source1' is not empty AND is a number
      *      OR
      *  Show 'target' if 'source1' is exactly 5.
+     *
+     * @var array
      */
     public array $controlDisplayRules = [];
 
@@ -159,6 +161,8 @@ protected function initLayout(): void
     /**
      * Setter for control display rules.
      *
+     * @param array $rules
+     *
      * @return $this
      */
     public function setControlsDisplayRules(array $rules = [])
@@ -171,7 +175,8 @@ public function setControlsDisplayRules(array $rules = [])
     /**
      * Set display rule for a group collection.
      *
-     * @param string|View $selector
+     * @param array $rules
+     * @param string|View          $selector
      *
      * @return $this
      */
@@ -188,7 +193,7 @@ public function setGroupDisplayRules(array $rules = [], $selector = '.atk-form-g
     }
 
     /**
-     * @param array|null $fields if null, then all "editable" fields will be added
+     * @param list|null $fields if null, then all "editable" fields will be added
      */
     #[\Override]
     public function setModel(Model $entity, ?array $fields = null): void
@@ -325,7 +330,7 @@ public function addControl(string $name, $control = [], array $fieldSeed = []):
     /**
      * Add header into the form, which appears as a separator.
      *
-     * @param string|array $title
+     * @param string|array<0|string, mixed> $title
      */
     public function addHeader($title = null): void
     {
@@ -335,7 +340,7 @@ public function addHeader($title = null): void
     /**
      * Creates a group of fields and returns layout.
      *
-     * @param string|array $title
+     * @param string|array<0|string, mixed> $title
      *
      * @return Form\Layout
      */
@@ -405,7 +410,7 @@ public function controlFactory(Field $field, $controlSeed = []): Control
     }
 
     /**
-     * @var array
+     * @var array>
      */
     protected array $typeToControl = [
         'boolean' => [Control\Checkbox::class],
diff --git a/src/Form/AbstractLayout.php b/src/Form/AbstractLayout.php
index bf6d258d22..6d9ddc6542 100644
--- a/src/Form/AbstractLayout.php
+++ b/src/Form/AbstractLayout.php
@@ -99,7 +99,7 @@ public function addControl(string $name, $control = [], array $fieldSeed = []):
      * Returns array of names of fields to automatically include them in form.
      * This includes all editable or visible fields of the model.
      *
-     * @return array
+     * @return list
      */
     protected function getModelFields(Model $model)
     {
@@ -109,7 +109,7 @@ protected function getModelFields(Model $model)
     /**
      * Sets form model and adds form controls.
      *
-     * @param array|null $fields
+     * @param list|null $fields
      */
     #[\Override]
     public function setModel(Model $entity, ?array $fields = null): void
@@ -150,7 +150,7 @@ public function getControl(string $name): Control
     /**
      * Adds Button into form layout.
      *
-     * @param Button|array $seed
+     * @param Button|array $seed
      *
      * @return Button
      */
diff --git a/src/Form/Control.php b/src/Form/Control.php
index 9624205f21..e763541ca0 100644
--- a/src/Form/Control.php
+++ b/src/Form/Control.php
@@ -55,7 +55,7 @@ class Control extends View
      * Placed as a pointing label below the field. This only works when Form\Control appears in a form. You can also
      * set this to object, such as \Atk4\Ui\Text otherwise HTML characters are escaped.
      *
-     * @var string|View|array
+     * @var string|View|array
      */
     public $hint;
 
@@ -130,7 +130,7 @@ protected function renderTemplateToHtml(): string
      * $control->onChange(new JsExpression('$(this).parents(\'.form\').form(\'submit\')'));
      *
      * @param JsExpressionable|JsCallbackSetClosure|array{JsCallbackSetClosure} $expr
-     * @param array|bool                                                        $defaults
+     * @param array|bool                                     $defaults
      */
     public function onChange($expr, $defaults = []): void
     {
diff --git a/src/Form/Control/Calendar.php b/src/Form/Control/Calendar.php
index 9ada1a0c3e..d6186ff1e4 100644
--- a/src/Form/Control/Calendar.php
+++ b/src/Form/Control/Calendar.php
@@ -23,6 +23,8 @@ class Calendar extends Input
     /**
      * Any other options you'd like to pass to Flatpickr JS.
      * See https://flatpickr.js.org/options/ for all possible options.
+     *
+     * @var array
      */
     public array $options = [];
 
diff --git a/src/Form/Control/Dropdown.php b/src/Form/Control/Dropdown.php
index 47d8561a3a..c59380feca 100644
--- a/src/Form/Control/Dropdown.php
+++ b/src/Form/Control/Dropdown.php
@@ -34,7 +34,7 @@ class Dropdown extends Input
     /** @var string The string to set as an empty values. */
     public $empty = "\u{00a0}"; // Unicode NBSP
 
-    /** @var array Dropdown options as per Fomantic-UI dropdown options. */
+    /** @var array Dropdown options as per Fomantic-UI dropdown options. */
     public $dropdownOptions = [];
 
     /**
@@ -140,7 +140,7 @@ public function setDropdownOption($option, $value): void
     /**
      * Set JS dropdown() options.
      *
-     * @param array $options
+     * @param array $options
      */
     public function setDropdownOptions($options): void
     {
diff --git a/src/Form/Control/DropdownCascade.php b/src/Form/Control/DropdownCascade.php
index 886aad9522..a5f229333f 100644
--- a/src/Form/Control/DropdownCascade.php
+++ b/src/Form/Control/DropdownCascade.php
@@ -109,6 +109,8 @@ public function getNewValues($id): array
      *
      * @param list $values
      * @param mixed                                                $value  the current field value
+     *
+     * @return list
      */
     private function getJsValues(array $values, $value): array
     {
diff --git a/src/Form/Control/Input.php b/src/Form/Control/Input.php
index b938444223..90add9fd95 100644
--- a/src/Form/Control/Input.php
+++ b/src/Form/Control/Input.php
@@ -47,10 +47,10 @@ class Input extends Form\Control
     /** @var string|Label Set label that will appear to the right of the input field. */
     public $labelRight;
 
-    /** @var Button|array|UserAction|null */
+    /** @var Button|array|UserAction|null */
     public $action;
 
-    /** @var Button|array|UserAction|null */
+    /** @var Button|array|UserAction|null */
     public $actionLeft;
 
     /**
@@ -142,8 +142,8 @@ protected function prepareRenderLabel($label, $spot)
     /**
      * Used only from renderView().
      *
-     * @param string|array|Button|UserAction|(AbstractView&ExecutorInterface) $button Button class or object
-     * @param string                                                          $spot   Template spot
+     * @param string|array|Button|UserAction|(AbstractView&ExecutorInterface) $button Button class or object
+     * @param string                                                                 $spot   Template spot
      *
      * @return Button
      */
@@ -239,6 +239,8 @@ protected function renderView(): void
     /**
      * Adds new action button.
      *
+     * @param array $defaults
+     *
      * @return Button
      */
     public function addAction(array $defaults = [])
diff --git a/src/Form/Control/Lookup.php b/src/Form/Control/Lookup.php
index 963c7b1f93..e3994d4fe9 100644
--- a/src/Form/Control/Lookup.php
+++ b/src/Form/Control/Lookup.php
@@ -64,7 +64,7 @@ class Lookup extends Input
      * true = will use "Add new" label
      * string = will use your string
      *
-     * @var bool|string|array|null
+     * @var bool|string|array<'button'|'fields'|'caption', mixed>|null
      */
     public $plus = false;
 
@@ -105,7 +105,7 @@ class Lookup extends Input
      *     }'),
      * ]]);
      *
-     * @var array
+     * @var array
      */
     public $settings = [];
 
diff --git a/src/Form/Control/Multiline.php b/src/Form/Control/Multiline.php
index c9d5fe17f0..f8a70c3601 100644
--- a/src/Form/Control/Multiline.php
+++ b/src/Form/Control/Multiline.php
@@ -100,11 +100,11 @@ class Multiline extends Form\Control
      * For example setting 'SuiDropdown' property globally.
      *  $componentProps = [Multiline::SELECT => ['floating' => true]].
      *
-     * @var array
+     * @var array>
      */
     public $componentProps = [];
 
-    /** @var array SuiTable component props */
+    /** @var array SuiTable component props */
     public $tableProps = [];
 
     /** @var array> Set Vue component to use per field type. */
@@ -138,7 +138,7 @@ class Multiline extends Form\Control
     /** @var bool Add row when tabbing out of last column in last row. */
     public $addOnTab = false;
 
-    /** @var array The definition of each field used in every multiline row. */
+    /** @var list> The definition of each field used in every multiline row. */
     private $fieldDefs;
 
     /** @var JsCallback */
@@ -147,13 +147,13 @@ class Multiline extends Form\Control
     /** @var \Closure(mixed, Form): (JsExpressionable|View|string|void)|null Function to execute when field change or row is delete. */
     protected $onChangeFunction;
 
-    /** @var array Set fields that will trigger onChange function. */
+    /** @var list Set fields that will trigger onChange function. */
     protected $eventFields;
 
-    /** @var array Collection of field errors. */
+    /** @var array> Collection of field errors. */
     private $rowErrors;
 
-    /** @var array The fields names used in each row. */
+    /** @var list The fields names used in each row. */
     public $rowFields;
 
     /** @var list> The data sent for each row. */
@@ -243,6 +243,11 @@ protected function init(): void
         });
     }
 
+    /**
+     * @param array> $values
+     *
+     * @return array>
+     */
     protected function typeCastLoadValues(array $values): array
     {
         $dataRows = [];
@@ -266,6 +271,7 @@ protected function typeCastLoadValues(array $values): array
      * that will trigger the callback when changed.
      *
      * @param \Closure(mixed, Form): (JsExpressionable|View|string|void) $fx
+     * @param list                                               $fields
      */
     public function onLineChange(\Closure $fx, array $fields): void
     {
@@ -304,6 +310,10 @@ public function getValue(): string
 
     /**
      * Validate each row and return errors if found.
+     *
+     * @param list> $rows
+     *
+     * @return array>
      */
     public function validate(array $rows): array
     {
@@ -371,6 +381,10 @@ public function saveRows(): self
 
     /**
      * Check for model validate error.
+     *
+     * @param array> $errors
+     *
+     * @return array>
      */
     protected function addModelValidateErrors(array $errors, string $rowId, Model $entity): array
     {
@@ -386,6 +400,8 @@ protected function addModelValidateErrors(array $errors, string $rowId, Model $e
 
     /**
      * Finds and returns Multiline row ID.
+     *
+     * @param array $row
      */
     private function getMlRowId(array $row): ?string
     {
@@ -402,7 +418,7 @@ private function getMlRowId(array $row): ?string
     }
 
     /**
-     * @param array|null $fields
+     * @param list|null $fields
      */
     #[\Override]
     public function setModel(Model $model, ?array $fields = null): void
@@ -425,6 +441,8 @@ public function setModel(Model $model, ?array $fields = null): void
      * Note: When using setReferenceModel you might need to set this corresponding field to neverPersist to true.
      * Otherwise, form will try to save 'multiline' field value as an array when form is save.
      * $multiline = $form->addControl('multiline', [Multiline::class], ['neverPersist' => true])
+     *
+     * @param list $fieldNames
      */
     public function setReferenceModel(string $refModelName, ?Model $entity = null, array $fieldNames = []): void
     {
@@ -440,6 +458,8 @@ public function setReferenceModel(string $refModelName, ?Model $entity = null, a
      *
      * Multiline uses Vue components in order to manage input type based on field type.
      * Component name and props are determine via the getComponentDefinition function.
+     *
+     * @return array
      */
     public function getFieldDef(Field $field): array
     {
@@ -460,6 +480,8 @@ public function getFieldDef(Field $field): array
     /**
      * Each field input, represent by a Vue component, is place within a table cell.
      * Cell properties can be customized via $field->ui['multiline'][Form\Control\Multiline::TABLE_CELL].
+     *
+     * @return array
      */
     protected function getSuiTableCellProps(Field $field): array
     {
@@ -474,6 +496,8 @@ protected function getSuiTableCellProps(Field $field): array
 
     /**
      * Return props for input component.
+     *
+     * @return array
      */
     protected function getSuiInputProps(Field $field): array
     {
@@ -484,6 +508,8 @@ protected function getSuiInputProps(Field $field): array
 
     /**
      * Return props for AtkDatePicker component.
+     *
+     * @return array
      */
     protected function getDatePickerProps(Field $field): array
     {
@@ -508,6 +534,8 @@ protected function getDatePickerProps(Field $field): array
 
     /**
      * Return props for Dropdown components.
+     *
+     * @return array
      */
     protected function getDropdownProps(Field $field): array
     {
@@ -526,6 +554,8 @@ protected function getDropdownProps(Field $field): array
 
     /**
      * Set property for AtkLookup component.
+     *
+     * @return array
      */
     protected function getLookupProps(Field $field): array
     {
@@ -569,6 +599,8 @@ public function setLookupOptionValue(Field $field, string $value): void
 
     /**
      * Component definition require at least a name and a props array.
+     *
+     * @return array
      */
     protected function getComponentDefinition(Field $field): array
     {
@@ -599,6 +631,9 @@ protected function getComponentDefinition(Field $field): array
         return $component;
     }
 
+    /**
+     * @return array
+     */
     protected function getFieldItems(Field $field, ?int $limit = 10): array
     {
         $items = [];
@@ -693,6 +728,8 @@ private function outputJson(): void
 
     /**
      * Return values associated with callback field.
+     *
+     * @return array
      */
     private function getCallbackValues(Model $entity): array
     {
@@ -763,6 +800,8 @@ private function getExpressionFields(Model $model): array
 
     /**
      * Return values associated to field expression.
+     *
+     * @return array
      */
     private function getExpressionValues(Model $entity): array
     {
diff --git a/src/Form/Control/ScopeBuilder.php b/src/Form/Control/ScopeBuilder.php
index eb5448a45e..56db045b97 100644
--- a/src/Form/Control/ScopeBuilder.php
+++ b/src/Form/Control/ScopeBuilder.php
@@ -17,6 +17,7 @@ class ScopeBuilder extends Form\Control
 {
     public $renderLabel = false;
 
+    /** @var array|bool> */
     public array $options = [
         'enum' => [
             'limit' => 250,
@@ -30,21 +31,21 @@ class ScopeBuilder extends Form\Control
      */
     public int $maxDepth = 5;
 
-    /** Fields to use for creating the rules. */
+    /** @var list Fields to use for creating the rules. */
     public array $fields = [];
 
     /** @var HtmlTemplate|null The template needed for the ScopeBuilder view. */
     public $scopeBuilderTemplate;
 
-    /** List of delimiters for auto-detection in order of priority. */
+    /** @var list List of delimiters for auto-detection in order of priority. */
     public static array $listDelimiters = [';', ','];
 
-    /** The date, time or datetime options. */
+    /** @var array The date, time or datetime options. */
     public array $atkdDateOptions = [
         'flatpickr' => [],
     ];
 
-    /** AtkLookup and Fomantic-UI dropdown options. */
+    /** @var array AtkLookup and Fomantic-UI dropdown options. */
     public array $atkLookupOptions = [
         'ui' => 'small basic button',
     ];
@@ -52,16 +53,18 @@ class ScopeBuilder extends Form\Control
     /** @var View The scopebuilder View. Assigned in init(). */
     protected $scopeBuilderView;
 
-    /** Definition of VueQueryBuilder rules. */
+    /** @var list> Definition of VueQueryBuilder rules. */
     protected array $rules = [];
 
     /**
      * Set Labels for Vue-Query-Builder
      * see https://dabernathy89.github.io/vue-query-builder/configuration.html#labels.
+     *
+     * @var array
      */
     public array $labels = [];
 
-    /** Default VueQueryBuilder query. */
+    /** @var array Default VueQueryBuilder query. */
     protected array $query = [];
 
     protected const OPERATOR_TEXT_EQUALS = 'equals';
@@ -350,6 +353,8 @@ protected function addFieldRule(Field $field): void
 
     /**
      * Set property for AtkLookup component.
+     *
+     * @return array
      */
     protected function getLookupProps(Field $field): array
     {
@@ -373,6 +378,8 @@ protected function getLookupProps(Field $field): array
 
     /**
      * Set property for AtkDatePicker component.
+     *
+     * @return array
      */
     protected function getDatePickerProps(Field $field): array
     {
@@ -422,6 +429,11 @@ protected function addReferenceRules(Field $field): void
         }
     }
 
+    /**
+     * @param array $defaults
+     *
+     * @return array
+     */
     protected function getRule(string $type, array $defaults = [], ?Field $field = null): array
     {
         $rule = static::$ruleTypes[$type] ?? static::$ruleTypes['default'];
@@ -449,6 +461,8 @@ protected function getRule(string $type, array $defaults = [], ?Field $field = n
     /**
      * Return an array of items ID and name for a field.
      * Return field enum, values or reference values.
+     *
+     * @return array
      */
     protected function getFieldItems(Field $field, ?int $limit = 250): array
     {
@@ -473,6 +487,10 @@ protected function getFieldItems(Field $field, ?int $limit = 250): array
 
     /**
      * Returns the choices array for Select field rule.
+     *
+     * @param array $options
+     *
+     * @return list
      */
     protected function getChoices(Field $field, array $options = []): array
     {
@@ -508,6 +526,8 @@ protected function renderView(): void
 
     /**
      * Converts an VueQueryBuilder query array to Condition or Scope.
+     *
+     * @param array $query
      */
     public function queryToScope(array $query): Scope\AbstractScope
     {
@@ -532,6 +552,8 @@ public function queryToScope(array $query): Scope\AbstractScope
 
     /**
      * Converts an VueQueryBuilder rule array to Condition or Scope.
+     *
+     * @param array $query
      */
     public function queryToCondition(array $query): Condition
     {
@@ -580,6 +602,10 @@ public function queryToCondition(array $query): Condition
 
     /**
      * Converts Scope or Condition to VueQueryBuilder query array.
+     *
+     * @param array $inputsMap
+     *
+     * @return array{type: string, query: array}
      */
     public function scopeToQuery(Scope\AbstractScope $scope, array $inputsMap = []): array
     {
@@ -612,7 +638,9 @@ public function scopeToQuery(Scope\AbstractScope $scope, array $inputsMap = []):
     /**
      * Converts a Condition to VueQueryBuilder query array.
      *
-     * @return array{rule: string, operator: string, value: string|null, option: array|null}
+     * @param array $inputsMap
+     *
+     * @return array{rule: string, operator: string, value: string|null, option: array|null}
      */
     public function conditionToQuery(Condition $condition, array $inputsMap = []): array
     {
@@ -683,6 +711,8 @@ public function conditionToQuery(Condition $condition, array $inputsMap = []): a
      * Return extra value option associate with certain inputType or null otherwise.
      *
      * @param mixed $value
+     *
+     * @return array
      */
     protected function getConditionOption(string $type, $value, Condition $condition): ?array
     {
diff --git a/src/Form/Control/TreeItemSelector.php b/src/Form/Control/TreeItemSelector.php
index 4c03361f4b..618d1d73d3 100644
--- a/src/Form/Control/TreeItemSelector.php
+++ b/src/Form/Control/TreeItemSelector.php
@@ -63,7 +63,7 @@ class TreeItemSelector extends Form\Control
      *
      * When adding nodes array into an item, it will automatically be treated as a group unless empty.
      *
-     * @var array
+     * @var list>}>
      */
     public $treeItems = [];
 
diff --git a/src/Form/Control/Upload.php b/src/Form/Control/Upload.php
index 99faccc73c..7b5deab492 100644
--- a/src/Form/Control/Upload.php
+++ b/src/Form/Control/Upload.php
@@ -44,7 +44,7 @@ class Upload extends Input
      * An array of string value for accept file type.
      * ex: ['.jpg', '.jpeg', '.png'] or ['images/*'].
      *
-     * @var array
+     * @var list
      */
     public $accept = [];
 
diff --git a/src/Form/Layout.php b/src/Form/Layout.php
index 7531a82398..c361154943 100644
--- a/src/Form/Layout.php
+++ b/src/Form/Layout.php
@@ -39,7 +39,7 @@ class Layout extends AbstractLayout
     /** @var HtmlTemplate|null Template holding input HTML. */
     public $inputTemplate;
 
-    /** @var array Seed for creating input hint View used in this layout. */
+    /** @var array Seed for creating input hint View used in this layout. */
     public $defaultHintSeed = [Label::class, 'class' => ['pointing']];
 
     #[\Override]
@@ -65,7 +65,7 @@ public function addButton($seed)
     }
 
     /**
-     * @param string|array $label
+     * @param string|array<0|string, mixed> $label
      *
      * @return $this
      */
@@ -79,7 +79,7 @@ public function addHeader($label)
     /**
      * Adds field group in form layout.
      *
-     * @param string|array $label
+     * @param string|array<0|string, mixed> $label
      *
      * @return static
      */
diff --git a/src/Form/Layout/Section.php b/src/Form/Layout/Section.php
index 139af75e64..ded125f93e 100644
--- a/src/Form/Layout/Section.php
+++ b/src/Form/Layout/Section.php
@@ -12,7 +12,7 @@
  */
 class Section extends View
 {
-    /** @var array */
+    /** @var array */
     public $formLayoutSeed = [Form\Layout::class];
 
     public Form $form;
diff --git a/src/Form/Layout/Section/Accordion.php b/src/Form/Layout/Section/Accordion.php
index 393d57ea84..4454c98815 100644
--- a/src/Form/Layout/Section/Accordion.php
+++ b/src/Form/Layout/Section/Accordion.php
@@ -15,7 +15,7 @@
  */
 class Accordion extends UiAccordion
 {
-    /** @var array */
+    /** @var array */
     public $formLayoutSeed = [Form\Layout::class];
 
     public Form $form;
diff --git a/src/Form/Layout/Section/Columns.php b/src/Form/Layout/Section/Columns.php
index 0fe17af223..81108f6f02 100644
--- a/src/Form/Layout/Section/Columns.php
+++ b/src/Form/Layout/Section/Columns.php
@@ -13,7 +13,7 @@
  */
 class Columns extends UiColumns
 {
-    /** @var array */
+    /** @var array */
     public $formLayoutSeed = [Form\Layout::class];
 
     public Form $form;
diff --git a/src/Form/Layout/Section/Tabs.php b/src/Form/Layout/Section/Tabs.php
index 9bd7c98f00..bf8da8b201 100644
--- a/src/Form/Layout/Section/Tabs.php
+++ b/src/Form/Layout/Section/Tabs.php
@@ -13,7 +13,7 @@
  */
 class Tabs extends UiTabs
 {
-    /** @var array */
+    /** @var array */
     public $formLayoutSeed = [Form\Layout::class];
 
     public Form $form;
diff --git a/src/Grid.php b/src/Grid.php
index 96526b62da..8b2e18f625 100644
--- a/src/Grid.php
+++ b/src/Grid.php
@@ -22,13 +22,13 @@ class Grid extends View
 {
     use HookTrait;
 
-    /** @var Menu|array|false Will be initialized to Menu object, however you can set this to false to disable menu. */
+    /** @var Menu|array|false Will be initialized to Menu object, however you can set this to false to disable menu. */
     public $menu;
 
     /** @var JsSearch|null */
     public $quickSearch;
 
-    /** @var array Field names to search for in Model. It will automatically add quicksearch component to grid if set. */
+    /** @var list Field names to search for in Model. It will automatically add quicksearch component to grid if set. */
     public $searchFieldNames = [];
 
     /**
@@ -86,10 +86,10 @@ class Grid extends View
 
     public $defaultTemplate = 'grid.html';
 
-    /** @var array Table\Column seed to use for ActionButtons. */
+    /** @var array Table\Column seed to use for ActionButtons. */
     protected $actionButtonsSeed = [Table\Column\ActionButtons::class];
 
-    /** @var array Table\Column seed to use for ActionMenu. */
+    /** @var array Table\Column seed to use for ActionMenu. */
     protected $actionMenuSeed = [Table\Column\ActionMenu::class, 'label' => 'Actions...'];
 
     #[\Override]
@@ -145,9 +145,9 @@ protected function initTable(): Table
      * Add new column to grid. If column with this name already exists,
      * an. Simply calls Table::addColumn(), so check that method out.
      *
-     * @param string|null                             $name            Data model field name
-     * @param array|Table\Column                      $columnDecorator
-     * @param ($name is null ? array{} : array|Field) $field
+     * @param string|null                                    $name            Data model field name
+     * @param array|Table\Column                      $columnDecorator
+     * @param ($name is null ? array{} : array|Field) $field
      *
      * @return Table\Column
      */
@@ -159,7 +159,7 @@ public function addColumn(?string $name, $columnDecorator = [], $field = [])
     /**
      * Add additional decorator for existing column.
      *
-     * @param array|Table\Column $seed
+     * @param array|Table\Column $seed
      *
      * @return Table\Column
      */
@@ -243,14 +243,14 @@ public function addItemsPerPageSelector(array $items = [10, 100, 1000], $label =
     /**
      * Add dynamic scrolling paginator.
      *
-     * @param int    $ipp          number of item per page to start with
-     * @param array  $options      an array with JS Scroll plugin options
-     * @param View   $container    the container holding the lister for scrolling purpose
-     * @param string $scrollRegion A specific template region to render. Render output is append to container HTML element.
+     * @param int                  $ipp          number of item per page to start with
+     * @param array $options      an array with JS Scroll plugin options
+     * @param View                 $container    the container holding the lister for scrolling purpose
+     * @param string               $scrollRegion A specific template region to render. Render output is append to container HTML element.
      *
      * @return $this
      */
-    public function addJsPaginator($ipp, $options = [], $container = null, $scrollRegion = 'Body')
+    public function addJsPaginator($ipp, array $options = [], $container = null, $scrollRegion = 'Body')
     {
         if ($this->paginator) {
             $this->paginator->destroy();
@@ -273,15 +273,15 @@ public function addJsPaginator($ipp, $options = [], $container = null, $scrollRe
      * Add dynamic scrolling paginator in container.
      * Use this to make table headers fixed.
      *
-     * @param int    $ipp             number of item per page to start with
-     * @param int    $containerHeight number of pixel the table container should be
-     * @param array  $options         an array with JS Scroll plugin options
-     * @param View   $container       the container holding the lister for scrolling purpose
-     * @param string $scrollRegion    A specific template region to render. Render output is append to container HTML element.
+     * @param int                  $ipp             number of item per page to start with
+     * @param int                  $containerHeight number of pixel the table container should be
+     * @param array $options         an array with JS Scroll plugin options
+     * @param View                 $container       the container holding the lister for scrolling purpose
+     * @param string               $scrollRegion    A specific template region to render. Render output is append to container HTML element.
      *
      * @return $this
      */
-    public function addJsPaginatorInContainer($ipp, $containerHeight, $options = [], $container = null, $scrollRegion = 'Body')
+    public function addJsPaginatorInContainer($ipp, $containerHeight, array $options = [], $container = null, $scrollRegion = 'Body')
     {
         $this->table->hasCollapsingCssActionColumn = false;
         $options = array_merge($options, [
@@ -299,8 +299,8 @@ public function addJsPaginatorInContainer($ipp, $containerHeight, $options = [],
      * By default, will query server when using Enter key on input search field.
      * You can change it to query server on each keystroke by passing $autoQuery true,.
      *
-     * @param array $fields       the list of fields to search for
-     * @param bool  $hasAutoQuery will query server on each key pressed
+     * @param list $fields       the list of fields to search for
+     * @param bool         $hasAutoQuery will query server on each key pressed
      */
     public function addQuickSearch($fields = [], $hasAutoQuery = false): void
     {
@@ -345,7 +345,7 @@ public function jsReload($args = [], $afterSuccess = null, array $apiConfig = []
      * Adds a new button into the action column on the right. For Crud this
      * column will already contain "delete" and "edit" buttons.
      *
-     * @param string|array|View                     $button     Label text, object or seed for the Button
+     * @param string|array|View              $button     Label text, object or seed for the Button
      * @param JsExpressionable|JsCallbackSetClosure $action
      * @param bool|\Closure(T): bool    $isDisabled
      *
@@ -439,7 +439,7 @@ private function getActionMenu()
      * An array of column name where filter is needed.
      * Leave empty to include all column in grid.
      *
-     * @param array|null $names an array with the name of column
+     * @param list $names an array with the name of column
      *
      * @return $this
      */
@@ -458,12 +458,12 @@ public function addFilterColumn($names = null)
      * Add a dropdown menu to header column.
      *
      * @param string                                                $columnName the name of column where to add dropdown
-     * @param array                                                 $items      the menu items to add
+     * @param array                             $items      the menu items to add
      * @param \Closure(string): (JsExpressionable|View|string|void) $fx         the callback function to execute when an item is selected
      * @param string                                                $icon       the icon
      * @param string                                                $menuId     the menu ID return by callback
      */
-    public function addDropdown(string $columnName, $items, \Closure $fx, $icon = 'caret square down', $menuId = null): void
+    public function addDropdown(string $columnName, array $items, \Closure $fx, $icon = 'caret square down', $menuId = null): void
     {
         $column = $this->table->columns[$columnName];
 
@@ -496,10 +496,10 @@ public function addPopup($columnName, $popup = null, $icon = 'caret square down'
      * Similar to addActionButton but when button is clicked, modal is displayed
      * with the $title and $callback is executed.
      *
-     * @param string|array|View                  $button
+     * @param string|array|View           $button
      * @param string                             $title
      * @param \Closure(View, mixed): void        $callback
-     * @param array                              $args       extra URL argument for callback
+     * @param array              $args       extra URL argument for callback
      * @param bool|\Closure(T): bool $isDisabled
      *
      * @return View
@@ -526,9 +526,9 @@ private function explodeSelectionValue(string $value): array
      * Similar to addActionButton but apply to a multiple records selection and display in menu.
      * When menu item is clicked, $callback is executed.
      *
-     * @param string|array|MenuItem                           $item
+     * @param string|array|MenuItem                    $item
      * @param \Closure(Jquery, list): JsExpressionable $callback
-     * @param array                                           $args     extra URL argument for callback
+     * @param array                           $args     extra URL argument for callback
      *
      * @return View
      */
@@ -546,10 +546,10 @@ public function addBulkAction($item, \Closure $callback, $args = [])
      * Similar to addModalAction but apply to a multiple records selection and display in menu.
      * When menu item is clicked, modal is displayed with the $title and $callback is executed.
      *
-     * @param string|array|MenuItem             $item
+     * @param string|array|MenuItem      $item
      * @param string                            $title
      * @param \Closure(View, list): void $callback
-     * @param array                             $args     extra URL argument for callback
+     * @param array             $args     extra URL argument for callback
      *
      * @return View
      */
@@ -613,7 +613,7 @@ public function applySort(): void
     }
 
     /**
-     * @param array|null $fields if null, then all "editable" fields will be added
+     * @param list|null $fields if null, then all "editable" fields will be added
      */
     #[\Override]
     public function setModel(Model $model, ?array $fields = null): void
diff --git a/src/GridLayout.php b/src/GridLayout.php
index 84a8c9c44b..a2083127f8 100644
--- a/src/GridLayout.php
+++ b/src/GridLayout.php
@@ -16,7 +16,7 @@ class GridLayout extends View
     /** @var int<1, 16> Number of columns */
     protected $columns = 2;
 
-    /** @var array */
+    /** @var array */
     protected $cssWideClasses = [
         1 => 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine',
         'ten', 'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen', 'sixteen',
diff --git a/src/HtmlTemplate.php b/src/HtmlTemplate.php
index 53b9024b8c..0e4979d5fb 100644
--- a/src/HtmlTemplate.php
+++ b/src/HtmlTemplate.php
@@ -69,6 +69,11 @@ public function getTagTree(string $tag): TagTree
         return $this->tagTrees[$tag];
     }
 
+    /**
+     * @param array $tagTrees
+     *
+     * @return array
+     */
     private function cloneTagTrees(array $tagTrees): array
     {
         $res = [];
@@ -427,6 +432,9 @@ public function loadFromString(string $str, bool $allowParseCache = false): self
         return $this;
     }
 
+    /**
+     * @param list $inputReversed
+     */
     protected function parseTemplateTree(array &$inputReversed, ?string $openedTag = null): TagTree
     {
         $tagTree = new TagTree($this, $openedTag ?? self::TOP_TAG);
diff --git a/src/HtmlTemplate/TagTree.php b/src/HtmlTemplate/TagTree.php
index be3194a13b..e2a282a117 100644
--- a/src/HtmlTemplate/TagTree.php
+++ b/src/HtmlTemplate/TagTree.php
@@ -19,7 +19,7 @@ class TagTree
 
     private string $tag;
 
-    /** @var array */
+    /** @var list */
     private array $children = [];
 
     public function __construct(HtmlTemplate $parentTemplate, string $tag)
@@ -57,7 +57,7 @@ public function getTag(): string
     }
 
     /**
-     * @return array
+     * @return list
      */
     public function getChildren(): array
     {
diff --git a/src/Js/JsConditionalForm.php b/src/Js/JsConditionalForm.php
index eb35b2b6df..a2d514d5ac 100644
--- a/src/Js/JsConditionalForm.php
+++ b/src/Js/JsConditionalForm.php
@@ -14,12 +14,15 @@ class JsConditionalForm implements JsExpressionable
     /** @var Form The form where rules should apply. */
     public $form;
 
-    /** @var array The field rules for that form. */
+    /** @var array The field rules for that form. */
     public array $fieldRules;
 
     /** @var string The HTML class name parent for input. */
     public $selector;
 
+    /**
+     * @param array $rules
+     */
     public function __construct(Form $form, array $rules = [], string $selector = '.field')
     {
         $this->form = $form;
@@ -29,6 +32,8 @@ public function __construct(Form $form, array $rules = [], string $selector = '.
 
     /**
      * Set field rules for the form.
+     *
+     * @param array $rules
      */
     public function setRules(array $rules): void
     {
diff --git a/src/Js/JsFunction.php b/src/Js/JsFunction.php
index ddfd246622..aef60e1ce8 100644
--- a/src/Js/JsFunction.php
+++ b/src/Js/JsFunction.php
@@ -25,7 +25,8 @@ class JsFunction implements JsExpressionable
     public string $indent = '';
 
     /**
-     * @param JsBlock|array|array $statements
+     * @param list                                             $args
+     * @param JsBlock|list|array $statements
      */
     public function __construct(array $args, $statements)
     {
diff --git a/src/Js/JsModal.php b/src/Js/JsModal.php
index 746a997e59..608517a43c 100644
--- a/src/Js/JsModal.php
+++ b/src/Js/JsModal.php
@@ -51,7 +51,7 @@ public function __construct($title, $url, array $args = [], string $dataType = '
      *
      * You can set option individually or supply an array.
      *
-     * @param string|array                        $options
+     * @param string|array         $options
      * @param ($options is array ? never : mixed) $value
      *
      * @return $this
diff --git a/src/Js/JsVueService.php b/src/Js/JsVueService.php
index d00fb81767..abdfccca13 100644
--- a/src/Js/JsVueService.php
+++ b/src/Js/JsVueService.php
@@ -22,6 +22,8 @@ public function createServiceChain(): JsChain
      * Create a new Vue instance using a component managed by ATK.
      *
      * This output js: atk.vueService.createAtkVue('id', 'component', {});
+     *
+     * @param array $data
      */
     public function createAtkVue(string $id, string $componentName, array $data = []): JsChain
     {
@@ -33,6 +35,8 @@ public function createAtkVue(string $id, string $componentName, array $data = []
      * External component should be load via js file and define properly.
      *
      * This output js: atk.vueService.createVue('id', 'component', {}, {});
+     *
+     * @param array $data
      */
     public function createVue(string $id, string $componentName, JsExpressionable $component, array $data = []): JsChain
     {
diff --git a/src/JsCallback.php b/src/JsCallback.php
index 4ab03d722a..c8b9683f2d 100644
--- a/src/JsCallback.php
+++ b/src/JsCallback.php
@@ -58,6 +58,7 @@ public function setConfirm($text = 'Are you sure?'): void
 
     /**
      * @param \Closure(Jquery, mixed, mixed, mixed, mixed, mixed, mixed, mixed, mixed, mixed, mixed): (JsExpressionable|View|string|void) $fx
+     * @param array                                                                                  $args
      *
      * @return $this
      */
diff --git a/src/JsPaginator.php b/src/JsPaginator.php
index f68e5a898c..29be0ccfb1 100644
--- a/src/JsPaginator.php
+++ b/src/JsPaginator.php
@@ -27,7 +27,7 @@ class JsPaginator extends JsCallback
      *  - tableContainerHeight: int Fixed height of table container in pixels.
      *  - tableHeaderColor: int|string HTML color for header.
      *
-     * @var array
+     * @var array
      */
     public $options = [];
 
diff --git a/src/JsSearch.php b/src/JsSearch.php
index da38d8557d..dbc56fec0c 100644
--- a/src/JsSearch.php
+++ b/src/JsSearch.php
@@ -16,7 +16,7 @@ class JsSearch extends View
     /** @var View The View to reload using this JsSearch. */
     public $reload;
 
-    /** @var array */
+    /** @var array */
     public $args = [];
 
     /**
diff --git a/src/Label.php b/src/Label.php
index 5560bc0066..e0ca6cdd71 100644
--- a/src/Label.php
+++ b/src/Label.php
@@ -12,14 +12,14 @@ class Label extends View
      * Add icon before label. If 'string' or seed is specified, it will
      * be converted to object by init().
      *
-     * @var View|array|string
+     * @var View|array|string
      */
     public $icon;
 
     /**
      * Icon to the right of the label.
      *
-     * @var View|array|string
+     * @var View|array|string
      */
     public $iconRight;
 
@@ -30,14 +30,14 @@ class Label extends View
      * Image to the left of the label. Cannot be used with label. If string
      * is set, will be used as Image source. Can also contain seed or object.
      *
-     * @var View|array|string
+     * @var View|array|string
      */
     public $image;
 
     /**
      * Image to the right of the label.
      *
-     * @var View|array|string
+     * @var View|array|string
      */
     public $imageRight;
 
diff --git a/src/Layout/NavigableInterface.php b/src/Layout/NavigableInterface.php
index 17cf6103f5..e1a9156e54 100644
--- a/src/Layout/NavigableInterface.php
+++ b/src/Layout/NavigableInterface.php
@@ -13,7 +13,7 @@ interface NavigableInterface
     /**
      * Add a group to left menu.
      *
-     * @param array $seed
+     * @param array $seed
      */
     public function addMenuGroup($seed): Menu;
 
@@ -22,9 +22,9 @@ public function addMenuGroup($seed): Menu;
      *
      * Will place item in a group if supply.
      *
-     * @param string|array                  $name
-     * @param string|array|JsExpressionable $action
-     * @param Menu                          $group
+     * @param string|array                                       $name
+     * @param string|array<0|string, string|int|false>|JsExpressionable $action
+     * @param Menu                                                      $group
      */
     public function addMenuItem($name, $action = null, $group = null): MenuItem;
 }
diff --git a/src/Lister.php b/src/Lister.php
index ba5ea94c20..15d7f2b619 100644
--- a/src/Lister.php
+++ b/src/Lister.php
@@ -77,14 +77,14 @@ protected function initChunks(): void
      * Will output x item in lister set per IPP until user scroll content to the end of page.
      * When this happen, content will be reload x number of items.
      *
-     * @param int    $ipp          Number of item per page
-     * @param array  $options      an array with JS Scroll plugin options
-     * @param View   $container    the container holding the lister for scrolling purpose
-     * @param string $scrollRegion A specific template region to render. Render output is append to container HTML element.
+     * @param int                  $ipp          Number of item per page
+     * @param array $options      an array with JS Scroll plugin options
+     * @param View                 $container    the container holding the lister for scrolling purpose
+     * @param string               $scrollRegion A specific template region to render. Render output is append to container HTML element.
      *
      * @return $this
      */
-    public function addJsPaginator($ipp, $options = [], $container = null, $scrollRegion = null)
+    public function addJsPaginator($ipp, array $options = [], $container = null, $scrollRegion = null)
     {
         $this->ipp = $ipp;
         $this->jsPaginator = JsPaginator::addTo($this, ['view' => $container, 'options' => $options]);
diff --git a/src/Loader.php b/src/Loader.php
index dd300e0627..073975e84e 100644
--- a/src/Loader.php
+++ b/src/Loader.php
@@ -39,7 +39,7 @@ class Loader extends View
     /** @var Callback for triggering */
     public $cb;
 
-    /** @var array URL arguments. */
+    /** @var array URL arguments. */
     public $urlArgs = [];
 
     #[\Override]
@@ -115,8 +115,9 @@ protected function renderView(): void
     /**
      * Return a JS action that will trigger the loader to start.
      *
-     * @param array $apiConfig
-     * @param string               $storeName
+     * @param array $args
+     * @param array                       $apiConfig
+     * @param string                                     $storeName
      *
      * @return JsChain
      */
diff --git a/src/Menu.php b/src/Menu.php
index be505488bd..06d8f04dbd 100644
--- a/src/Menu.php
+++ b/src/Menu.php
@@ -36,7 +36,7 @@ class Menu extends View
     /**
      * $seed can also be name here.
      *
-     * @param string|array|MenuItem                                                      $item
+     * @param string|array|MenuItem                                               $item
      * @param string|array<0|string, string|int|false>|JsExpressionable|Model\UserAction $action
      *
      * @return MenuItem
@@ -79,7 +79,7 @@ public function addHeader($name)
     /**
      * Adds sub-menu.
      *
-     * @param string|array $name
+     * @param string|array<0|'title'|'text'|'name'|'icon', string> $name
      *
      * @return Menu
      */
@@ -111,7 +111,7 @@ public function addMenu($name)
     /**
      * Adds menu group.
      *
-     * @param string|array $name
+     * @param string|array<0|'title'|'text'|'name'|'icon', string> $name
      *
      * @return Menu
      */
diff --git a/src/Modal.php b/src/Modal.php
index 9bd6815873..773bb279cc 100644
--- a/src/Modal.php
+++ b/src/Modal.php
@@ -45,15 +45,15 @@ class Modal extends View
     public $cb;
     /** @var View|null */
     public $cbView;
-    /** @var array */
+    /** @var array */
     public $args = [];
-    /** @var array */
+    /** @var array */
     public $options = [];
 
     /** @var string Currently only "json" response type is supported. */
     public $type = 'json';
 
-    /** @var array Add ability to add CSS classes to "content" div. */
+    /** @var list Add ability to add CSS classes to "content" div. */
     public $contentClass = ['img', 'content', 'atk-dialog-content'];
 
     /**
@@ -106,7 +106,7 @@ public function enableCallback(): void
     /**
      * Add CSS classes to "content" div.
      *
-     * @param string|array $class
+     * @param string|list $class
      */
     public function addContentClass($class): void
     {
@@ -118,6 +118,8 @@ public function addContentClass($class): void
      *
      * Example: $button->on('click', $modal->jsShow());
      *
+     * @param array $args
+     *
      * @return JsChain
      */
     public function jsShow(array $args = []): JsExpressionable
diff --git a/src/Paginator.php b/src/Paginator.php
index a176a5a2c2..8e662c6b5b 100644
--- a/src/Paginator.php
+++ b/src/Paginator.php
@@ -43,6 +43,8 @@ class Paginator extends View
     /**
      * Add extra parameter to the reload view
      * as JsReload urlOptions.
+     *
+     * @var array
      */
     public array $reloadArgs = [];
 
@@ -91,6 +93,8 @@ public function getCurrentPage(): int
      *
      * Array will contain '[', ']', denoting "first", "last" items, '...' for the spacer and any
      * other integer value for a regular page link.
+     *
+     * @return list
      */
     public function getPaginatorItems(): array
     {
@@ -157,7 +161,7 @@ protected function getPageUrl($page): string
      * Add extra argument to the reload view.
      * These arguments will be set as urlOptions to JsReload.
      *
-     * @param array $args
+     * @param array $args
      */
     public function addReloadArgs($args): void
     {
diff --git a/src/Panel/Content.php b/src/Panel/Content.php
index cd05077925..b2f7385a77 100644
--- a/src/Panel/Content.php
+++ b/src/Panel/Content.php
@@ -58,6 +58,8 @@ public function onLoad(\Closure $fx): void
     /**
      * Return an array of CSS selector where content will be
      * cleared on reload.
+     *
+     * @return list
      */
     public function getClearSelector(): array
     {
diff --git a/src/Panel/Right.php b/src/Panel/Right.php
index d19adb52e3..0f5e64e637 100644
--- a/src/Panel/Right.php
+++ b/src/Panel/Right.php
@@ -27,7 +27,7 @@ class Right extends View implements Loadable
 
     /** @var Modal|null */
     public $closeModal;
-    /** @var array Confirmation Modal default */
+    /** @var array Confirmation Modal default */
     public $defaultModal = [Modal::class, 'class' => ['mini']];
 
     /** @var View|null The content to display inside flyout */
@@ -39,7 +39,7 @@ class Right extends View implements Loadable
     /** @var bool can be closed via esc key. */
     protected $hasEscAway = true;
 
-    /** @var array The default content seed. */
+    /** @var array The default content seed. */
     public $dynamic = [Content::class];
 
     /** @var string The CSS selector on where to add close panel event triggering for closing it. */
@@ -91,7 +91,7 @@ public function jsService(): JsChain
      * Return JS expression need to open panel via JS panelService.
      *
      * @param array $urlArgs       the argument to include when dynamic content panel open
-     * @param array                 $dataAttribute the data attribute name to include in reload from the triggering element
+     * @param list          $dataAttribute the data attribute name to include in reload from the triggering element
      * @param string|null           $activeCss     the CSS class name to apply on triggering element when panel is open
      * @param JsExpressionable      $jsTrigger     JS expression that trigger panel to open. Default = $(this).
      */
@@ -108,6 +108,8 @@ public function jsOpen(array $urlArgs = [], array $dataAttribute = [], ?string $
 
     /**
      * Will reload panel passing args as Get param via JS flyoutService.
+     *
+     * @param array $args
      */
     public function jsPanelReload(array $args = []): JsExpressionable
     {
@@ -177,6 +179,9 @@ public function jsToggleWarning(): JsExpressionable
         return (new Jquery('#' . $this->name . ' ' . $this->warningSelector))->toggleClass($this->warningTrigger);
     }
 
+    /**
+     * @return array
+     */
     public function getPanelOptions(): array
     {
         $res = [
diff --git a/src/Popup.php b/src/Popup.php
index 583a08b805..cd2dae83a5 100644
--- a/src/Popup.php
+++ b/src/Popup.php
@@ -45,7 +45,7 @@ class Popup extends View
      */
     public $target = false;
 
-    /** @var array Popup options as defined in Fomantic-UI popup module. */
+    /** @var array Popup options as defined in Fomantic-UI popup module. */
     public $popOptions = [];
 
     /** @var Callback|null The callback use to generate dynamic content. */
@@ -55,7 +55,7 @@ class Popup extends View
      * The dynamic View to load inside the popup
      * when dynamic content is use.
      *
-     * @var View|array
+     * @var View|array
      */
     public $dynamicContent = [View::class];
 
diff --git a/src/Table.php b/src/Table.php
index f64f9c558d..c8f82ebac4 100644
--- a/src/Table.php
+++ b/src/Table.php
@@ -29,7 +29,7 @@ class Table extends Lister
      */
     public $reload;
 
-    /** @var array> Contains list of declared columns. Value will always be a column object. */
+    /** @var array> Contains list of declared columns. Value will always be a column object. */
     public $columns = [];
 
     /**
@@ -51,7 +51,7 @@ class Table extends Lister
     /** @var bool Setting this to false will hide header row. */
     public $header = true;
 
-    /** @var array Contains list of totals accumulated during the render process. */
+    /** @var array Contains list of totals accumulated during the render process. */
     public $totals = [];
 
     /** @var HtmlTemplate|null Contain the template for the "Head" type row. */
@@ -130,9 +130,9 @@ protected function initChunks(): void
      * If you don't want table column to be associated with model field, then
      * pass $name parameter as null.
      *
-     * @param string|null                             $name            Data model field name
-     * @param array|Table\Column                      $columnDecorator
-     * @param ($name is null ? array{} : array|Field) $field
+     * @param string|null                                    $name            Data model field name
+     * @param array|Table\Column                      $columnDecorator
+     * @param ($name is null ? array{} : array|Field) $field
      *
      * @return Table\Column
      */
@@ -190,7 +190,7 @@ private function _addUnchecked(Table\Column $column): Table\Column
     /**
      * Set Popup action for columns filtering.
      *
-     * @param array $cols an array with columns name that need filtering
+     * @param list $cols an array with columns name that need filtering
      */
     public function setFilterColumn($cols = null): void
     {
@@ -223,7 +223,7 @@ public function setFilterColumn($cols = null): void
     /**
      * Add column Decorator.
      *
-     * @param array|Table\Column $seed
+     * @param array|Table\Column $seed
      *
      * @return Table\Column
      */
@@ -246,12 +246,14 @@ public function addDecorator(string $name, $seed)
 
     /**
      * Return array of column decorators for particular column.
+     *
+     * @return list
      */
     public function getColumnDecorators(string $name): array
     {
-        $dec = $this->columns[$name];
+        $decorator = $this->columns[$name];
 
-        return is_array($dec) ? $dec : [$dec];
+        return is_array($decorator) ? $decorator : [$decorator];
     }
 
     /**
@@ -268,7 +270,7 @@ protected function getColumn(string $name)
     }
 
     /**
-     * @var array
+     * @var array>
      */
     protected array $typeToDecorator = [
         'atk4_money' => [Table\Column\Money::class],
@@ -280,7 +282,7 @@ protected function getColumn(string $name)
      * Will come up with a column object based on the field object supplied.
      * By default will use default column.
      *
-     * @param array|Table\Column $seed
+     * @param array|Table\Column $seed
      *
      * @return Table\Column
      */
@@ -303,12 +305,12 @@ public function decoratorFactory(Field $field, $seed = [])
      * name and size.
      *
      * @param \Closure(Jquery, mixed): (JsExpressionable|View|string|void) $fx             a callback function with columns widths as parameter
-     * @param array                                              $widths         ex: [100, 200, 300, 100]
-     * @param array                                                        $resizerOptions column-resizer module options, see https://www.npmjs.com/package/column-resizer
+     * @param list                                                    $widths         ex: [100, 200, 300, 100]
+     * @param array                                         $resizerOptions column-resizer module options, see https://www.npmjs.com/package/column-resizer
      *
      * @return $this
      */
-    public function resizableColumn($fx = null, $widths = null, $resizerOptions = [])
+    public function resizableColumn($fx = null, $widths = null, array $resizerOptions = [])
     {
         $options = [];
         if ($fx !== null) {
@@ -331,7 +333,7 @@ public function resizableColumn($fx = null, $widths = null, $resizerOptions = []
     }
 
     #[\Override]
-    public function addJsPaginator($ipp, $options = [], $container = null, $scrollRegion = 'Body')
+    public function addJsPaginator($ipp, array $options = [], $container = null, $scrollRegion = 'Body')
     {
         $options = array_merge($options, ['appendTo' => 'tbody']);
 
@@ -354,7 +356,7 @@ public function addTotals($plan = []): void
     }
 
     /**
-     * @param array|null $fields if null, then all "editable" fields will be added
+     * @param list|null $fields if null, then all "editable" fields will be added
      */
     #[\Override]
     public function setModel(Model $model, ?array $fields = null): void
diff --git a/src/Table/Column.php b/src/Table/Column.php
index 54541f7933..2a148b8c41 100644
--- a/src/Table/Column.php
+++ b/src/Table/Column.php
@@ -54,11 +54,14 @@ class Column
     /** @var bool Include header action tag in rendering or not. */
     public $hasHeaderAction = false;
 
-    /** @var array|null The tag value required for getTag when using an header action. */
+    /** @var array<0|1|2, mixed>|null The tag value required for getTag when using an header action. */
     public $headerActionTag;
 
     private string $nameInTableCache;
 
+    /**
+     * @param array $defaults
+     */
     public function __construct(array $defaults = [])
     {
         $this->setDefaults($defaults);
@@ -189,6 +192,7 @@ public function setHeaderPopupIcon($icon): void
     /**
      * Add a dropdown header menu.
      *
+     * @param array                                     $items
      * @param \Closure(string, string): (JsExpressionable|View|string|void) $fx
      * @param string                                                        $icon
      * @param string|null                                                   $menuId the menu name
@@ -212,11 +216,11 @@ public function addDropdown(array $items, \Closure $fx, $icon = 'caret square do
      * This method return a callback where you can detect
      * menu item change via $cb->onMenuItem($item) function.
      *
-     * @param array $items
+     * @param list $items
      *
      * @return Column\JsHeaderDropdownCallback
      */
-    public function setHeaderDropdown($items, string $icon = 'caret square down', ?string $menuId = null): JsCallback
+    public function setHeaderDropdown(array $items, string $icon = 'caret square down', ?string $menuId = null): JsCallback
     {
         $this->hasHeaderAction = true;
         $id = $this->name . '_ac';
@@ -292,6 +296,8 @@ public function setAttr($attr, $value, $position = 'body')
 
     /**
      * @param array> ...$attributesArr
+     *
+     * @return array>
      */
     protected function mergeTagAttributes(array ...$attributesArr): array
     {
@@ -310,7 +316,10 @@ protected function mergeTagAttributes(array ...$attributesArr): array
     }
 
     /**
-     * @param 'head'|'body'|'foot' $position
+     * @param 'head'|'body'|'foot'               $position
+     * @param array> $attr
+     *
+     * @return array>
      */
     public function getTagAttributes(string $position, array $attr = []): array
     {
@@ -326,8 +335,8 @@ public function getTagAttributes(string $position, array $attr = []): array
      * added through addClass and setAttr.
      *
      * @param 'head'|'body'|'foot'                                                                                     $position
-     * @param array>                                                                 $attr
-     * @param string|array, 2?: string|array|null}|string>|null $value
+     * @param array>                                                                  $attr
+     * @param string|list, 2?: string|list|null}|string>|null $value
      */
     public function getTag(string $position, $attr, $value): string
     {
@@ -398,7 +407,7 @@ public function getHeaderCellHtml(?Field $field = null, $value = null): string
     /**
      * Return HTML for a total value of a specific field.
      *
-     * @param mixed $value
+     * @param int|float $value
      */
     public function getTotalsCellHtml(Field $field, $value): string
     {
@@ -415,6 +424,8 @@ public function getTotalsCellHtml(Field $field, $value): string
      * will also be formatted before inserting, see UI Persistence formatting in the documentation.
      *
      * If you need to format data manually, you can use $this->table->onHook(Lister::HOOK_BEFORE_ROW or Lister::HOOK_AFTER_ROW, ...);
+     *
+     * @param array> $attr
      */
     public function getDataCellHtml(?Field $field = null, array $attr = []): string
     {
diff --git a/src/Table/Column/ActionButtons.php b/src/Table/Column/ActionButtons.php
index 15d723f7a9..a2a19568b7 100644
--- a/src/Table/Column/ActionButtons.php
+++ b/src/Table/Column/ActionButtons.php
@@ -39,7 +39,7 @@ protected function init(): void
     /**
      * Adds a new button which will execute $action when clicked.
      *
-     * @param string|array|View                                       $button
+     * @param string|array|View                                $button
      * @param JsExpressionable|JsCallbackSetClosure|ExecutorInterface $action
      * @param bool|\Closure(T): bool                      $isDisabled
      *
@@ -78,11 +78,11 @@ public function addButton($button, $action = null, string $confirmMsg = '', $isD
      * Adds a new button which will open a modal dialog and dynamically
      * load contents through $callback. Will pass a virtual page.
      *
-     * @param string|array|View                  $button
-     * @param string|array                       $defaults   modal title or modal defaults array
+     * @param string|array|View           $button
+     * @param string|array                $defaults   modal title or modal defaults array
      * @param \Closure(View, mixed): void        $callback
      * @param View                               $owner
-     * @param array                              $args
+     * @param array              $args
      * @param bool|\Closure(T): bool $isDisabled
      *
      * @return View
diff --git a/src/Table/Column/ActionMenu.php b/src/Table/Column/ActionMenu.php
index 0d32e4670a..7726ec3e6a 100644
--- a/src/Table/Column/ActionMenu.php
+++ b/src/Table/Column/ActionMenu.php
@@ -22,7 +22,7 @@
  */
 class ActionMenu extends Table\Column
 {
-    /** @var array Menu items collections. */
+    /** @var list Menu items collections. */
     protected $items = [];
 
     /** @var array(T): bool> Callbacks as defined in UserAction->enabled for evaluating row-specific if an action is enabled. */
@@ -34,7 +34,7 @@ class ActionMenu extends Table\Column
     /** @var string Dropdown module CSS class name as per Formantic-UI. */
     public $ui = 'small dropdown button';
 
-    /** @var array The dropdown module option setting as per Fomantic-UI. */
+    /** @var array The dropdown module option setting as per Fomantic-UI. */
     public $options = ['action' => 'hide'];
 
     /** @var string Button icon to use for display dropdown. */
@@ -115,7 +115,7 @@ public function getHeaderCellHtml(?Field $field = null, $value = null): string
     #[\Override]
     public function getDataCellTemplate(?Field $field = null): string
     {
-        if (!$this->items) {
+        if ($this->items === []) {
             return '';
         }
 
diff --git a/src/Table/Column/FilterModel.php b/src/Table/Column/FilterModel.php
index 6df1af9b31..ec1048faa0 100644
--- a/src/Table/Column/FilterModel.php
+++ b/src/Table/Column/FilterModel.php
@@ -114,6 +114,9 @@ public function afterInit(): void
         });
     }
 
+    /**
+     * @return array|null
+     */
     public function recallData(): ?array
     {
         return $this->recall('data');
@@ -129,6 +132,8 @@ abstract public function setConditionForModel(Model $model): void;
      * Method that will set Field display condition in a form.
      * If form filter need to have a field display at certain condition, then
      * override this method in your FilterModel\TypeModel.
+     *
+     * @return array>
      */
     public function getFormDisplayRules(): array
     {
diff --git a/src/Table/Column/FilterPopup.php b/src/Table/Column/FilterPopup.php
index 59e0a0f63c..f6976392af 100644
--- a/src/Table/Column/FilterPopup.php
+++ b/src/Table/Column/FilterPopup.php
@@ -88,6 +88,9 @@ public function isFilterOn(): bool
         return $this->recallData() !== null;
     }
 
+    /**
+     * @return array|null
+     */
     public function recallData(): ?array
     {
         return $this->form->entity->recallData();
diff --git a/src/Table/Column/KeyValue.php b/src/Table/Column/KeyValue.php
index 223b318e71..b3565c6c06 100644
--- a/src/Table/Column/KeyValue.php
+++ b/src/Table/Column/KeyValue.php
@@ -39,6 +39,7 @@
  */
 class KeyValue extends Table\Column
 {
+    /** @var array */
     public array $values;
 
     #[\Override]
diff --git a/src/Table/Column/Link.php b/src/Table/Column/Link.php
index 69637eb18b..280dd4cfe6 100644
--- a/src/Table/Column/Link.php
+++ b/src/Table/Column/Link.php
@@ -83,6 +83,8 @@ class Link extends Table\Column
 
     /**
      * @param string|array<0|string, string|int|false> $page
+     * @param array                $args
+     * @param array                     $defaults
      */
     public function __construct($page = [], array $args = [], array $defaults = [])
     {
diff --git a/src/Tabs.php b/src/Tabs.php
index ec8fba39a4..008f4b8649 100644
--- a/src/Tabs.php
+++ b/src/Tabs.php
@@ -17,6 +17,7 @@ class Tabs extends View
     /**
      * @param string|TabsTab                                                                                    $name
      * @param \Closure(VirtualPage, mixed, mixed, mixed, mixed, mixed, mixed, mixed, mixed, mixed, mixed): void $callback
+     * @param array                                                                              $settings
      *
      * @return View
      */
@@ -41,7 +42,8 @@ public function addTab($name, ?\Closure $callback = null, array $settings = [])
      * page/url when activated.
      *
      * @param string|TabsTab                           $name
-     * @param string|array<0|string, string|int|false> $page URL to open inside a tab
+     * @param string|array<0|string, string|int|false> $page     URL to open inside a tab
+     * @param array                     $settings
      */
     public function addTabUrl($name, $page, array $settings = []): void
     {
@@ -54,7 +56,8 @@ public function addTabUrl($name, $page, array $settings = []): void
     /**
      * Add a tab menu item.
      *
-     * @param string|TabsTab $name
+     * @param string|TabsTab       $name
+     * @param array $settings
      *
      * @return TabsTab|View tab menu item view
      */
diff --git a/src/TabsTab.php b/src/TabsTab.php
index 3cee55a290..fb3f1236c0 100644
--- a/src/TabsTab.php
+++ b/src/TabsTab.php
@@ -12,7 +12,7 @@ class TabsTab extends MenuItem
     /** @var string */
     public $path;
 
-    /** @var array Tab settings */
+    /** @var array Tab settings */
     public $settings = [];
 
     /**
diff --git a/src/UserAction/BasicExecutor.php b/src/UserAction/BasicExecutor.php
index 0fd52d31b4..efb9f5b950 100644
--- a/src/UserAction/BasicExecutor.php
+++ b/src/UserAction/BasicExecutor.php
@@ -33,7 +33,7 @@ class BasicExecutor extends View implements ExecutorInterface
     /** @var string display message when action is disabled */
     public $disableMsg = 'Action is disabled and cannot be executed';
 
-    /** @var Button|array Button that trigger the action. Either as an array seed or object */
+    /** @var Button|array Button that trigger the action. Either as an array seed or object */
     public $executorButton;
 
     /** @var array */
@@ -42,9 +42,6 @@ class BasicExecutor extends View implements ExecutorInterface
     /** @var string display message when missing arguments */
     public $missingArgsMsg = 'Insufficient arguments';
 
-    /** @var array list of validated arguments */
-    protected $validArguments = [];
-
     /** @var JsExpressionable|\Closure($this, T): ?JsBlock JS expression to return if action was successful, e.g "new JsToast('Thank you')" */
     protected $jsSuccess;
 
@@ -67,6 +64,8 @@ public function setAction(Model\UserAction $action)
 
     /**
      * Provide values for named arguments.
+     *
+     * @param array $arguments
      */
     public function setArguments(array $arguments): void
     {
diff --git a/src/UserAction/ExecutorFactory.php b/src/UserAction/ExecutorFactory.php
index 09e7c20d72..12dc144187 100644
--- a/src/UserAction/ExecutorFactory.php
+++ b/src/UserAction/ExecutorFactory.php
@@ -36,7 +36,7 @@ class ExecutorFactory
      * Basic type can be changed or added globally via the registerTypeExecutor method.
      * A specific model/action executor may be set via the registerExecutor method.
      *
-     * @var array
+     * @var array>
      */
     protected $executorSeed = [
         self::JS_EXECUTOR => [JsCallbackExecutor::class],
@@ -67,7 +67,7 @@ class ExecutorFactory
      * They can be store per either view type or
      * model/action name.
      *
-     * @var array
+     * @var array|View>>
      */
     protected $triggerSeed = [
         self::TABLE_BUTTON => [
@@ -81,6 +81,8 @@ class ExecutorFactory
 
     /**
      * Register an executor for a basic type.
+     *
+     * @param array $seed
      */
     public function registerTypeExecutor(string $type, array $seed): void
     {
@@ -89,6 +91,8 @@ public function registerTypeExecutor(string $type, array $seed): void
 
     /**
      * Register an executor instance for a specific model User action.
+     *
+     * @param array $seed
      */
     public function registerExecutor(UserAction $action, array $seed): void
     {
@@ -99,7 +103,7 @@ public function registerExecutor(UserAction $action, array $seed): void
      * Register a trigger for a specific View type.
      * Trigger can be specify per action or per model/action.
      *
-     * @param array|View $seed
+     * @param array|View $seed
      */
     public function registerTrigger(string $type, $seed, UserAction $action, bool $isSpecific = false): void
     {
@@ -200,6 +204,8 @@ protected function createActionTrigger(UserAction $action, ?string $type = null)
 
     /**
      * Return executor default trigger seed based on type.
+     *
+     * @return array
      */
     protected function getDefaultTrigger(UserAction $action, ?string $type = null): array
     {
@@ -253,6 +259,8 @@ protected function getActionCaption(UserAction $action, ?string $type = null): s
 
     /**
      * Return Add action seed for menu item.
+     *
+     * @return array
      */
     protected function getAddMenuItem(UserAction $action): array
     {
diff --git a/src/UserAction/FormExecutor.php b/src/UserAction/FormExecutor.php
index ee4df28676..850554fe7e 100644
--- a/src/UserAction/FormExecutor.php
+++ b/src/UserAction/FormExecutor.php
@@ -38,7 +38,7 @@ public function initPreview(): void
      * Returns array of names of fields.
      * This includes all editable or visible fields of the model.
      *
-     * @return array
+     * @return list
      */
     protected function getModelFields(Model $model)
     {
diff --git a/src/UserAction/JsCallbackExecutor.php b/src/UserAction/JsCallbackExecutor.php
index 00cef381fb..322a63ef69 100644
--- a/src/UserAction/JsCallbackExecutor.php
+++ b/src/UserAction/JsCallbackExecutor.php
@@ -112,7 +112,7 @@ public function executeModelAction(): void
                     ?: ($success ?? new JsToast('Success' . (is_string($return) ? (': ' . $return) : ''))));
 
                 return $js;
-            }, array_map(static fn () => true, $this->action->args));
+            }, array_map(static fn () => true, $this->action->args)); // @phpstan-ignore argument.type
         });
     }
 }
diff --git a/src/UserAction/PanelExecutor.php b/src/UserAction/PanelExecutor.php
index 572ee786e9..b38db26866 100644
--- a/src/UserAction/PanelExecutor.php
+++ b/src/UserAction/PanelExecutor.php
@@ -26,7 +26,7 @@ class PanelExecutor extends Right implements JsExecutorInterface
 
     public const HOOK_STEP = self::class . '@onStep';
 
-    /** @var array No need for dynamic content. It is manage with step loader. */
+    /** No need for dynamic content. It is managed with step loader. */
     public $dynamic = [];
     public $hasClickAway = false;
 
diff --git a/src/UserAction/StepExecutorTrait.php b/src/UserAction/StepExecutorTrait.php
index 340d0560fe..786f8a70de 100644
--- a/src/UserAction/StepExecutorTrait.php
+++ b/src/UserAction/StepExecutorTrait.php
@@ -17,7 +17,7 @@
 
 trait StepExecutorTrait
 {
-    /** @var array The steps need to complete the action. */
+    /** @var list The steps need to complete the action. */
     protected array $steps;
 
     /** @var string current step. */
@@ -38,7 +38,7 @@ trait StepExecutorTrait
     /** @var UserAction The action to execute. */
     public $action;
 
-    /** @var array will collect data while doing action step. */
+    /** @var array> will collect data while doing action step. */
     private $actionData = [];
 
     /** @var bool */
@@ -47,7 +47,7 @@ trait StepExecutorTrait
     /** @var JsExpressionable|\Closure($this, T, mixed, mixed): ?JsBlock JS expression to return if action was successful, e.g "new JsToast('Thank you')" */
     public $jsSuccess;
 
-    /** @var array A seed for creating form in order to edit arguments/fields user entry. */
+    /** @var array A seed for creating form in order to edit arguments/fields user entry. */
     public $formSeed = [Form::class];
 
     /** @var string can be "console", "text", or "html". Determine how preview step will display information. */
@@ -84,6 +84,8 @@ protected function addFormTo(View $view): Form
 
     /**
      * Will add field into form based on $fields array.
+     *
+     * @param array $fields
      */
     protected function setFormField(Form $form, array $fields, string $step): Form
     {
@@ -246,6 +248,8 @@ protected function doFinal(View $page): void
 
     /**
      * Get how many steps is required for this action.
+     *
+     * @return list
      */
     protected function getSteps(): array
     {
@@ -275,16 +279,12 @@ protected function isLastStep(string $step): bool
 
     protected function getPreviousStep(string $step): string
     {
-        $steps = array_values($this->steps);
-
-        return $steps[array_search($step, $steps, true) - 1];
+        return $this->steps[array_search($step, $this->steps, true) - 1];
     }
 
     protected function getNextStep(string $step): string
     {
-        $steps = array_values($this->steps);
-
-        return $steps[array_search($step, $steps, true) + 1];
+        return $this->steps[array_search($step, $this->steps, true) + 1];
     }
 
     protected function getStep(): string
@@ -412,13 +412,16 @@ protected function jsStepSubmit(string $step): JsBlock
         return $js;
     }
 
+    /**
+     * @return array
+     */
     protected function getActionData(string $step): array
     {
         return $this->actionData[$step] ?? [];
     }
 
     /**
-     * @param array $fields
+     * @param list $fields
      */
     private function setActionDataFromEntity(string $step, Model $entity, array $fields): void
     {
@@ -446,6 +449,10 @@ protected function getActionPreview()
 
     /**
      * Utility for retrieving Argument.
+     *
+     * @param array $data
+     *
+     * @return list
      */
     protected function getActionArgs(array $data): array
     {
diff --git a/src/UserAction/VpExecutor.php b/src/UserAction/VpExecutor.php
index bda3a8d9cb..82446d952a 100644
--- a/src/UserAction/VpExecutor.php
+++ b/src/UserAction/VpExecutor.php
@@ -42,7 +42,7 @@ class VpExecutor extends VirtualPage implements JsExecutorInterface
     /** @var array */
     public $stepListItems = ['args' => 'Fill argument(s)', 'fields' => 'Edit Record(s)', 'preview' => 'Preview', 'final' => 'Complete'];
 
-    /** @var array */
+    /** @var array */
     public $cancelButtonSeed = [Button::class, ['Cancel', 'class.small left floated basic blue' => true, 'icon' => 'left arrow']];
 
     #[\Override]
diff --git a/src/View.php b/src/View.php
index 262f00f4f5..e0fe14991e 100644
--- a/src/View.php
+++ b/src/View.php
@@ -26,7 +26,7 @@ class View extends AbstractView
     /**
      * When you call renderAll() this will be populated with JavaScript chains.
      *
-     * @var array<1|string, array>
+     * @var array<1|string, list>
      *
      * @internal
      */
@@ -49,7 +49,7 @@ class View extends AbstractView
      */
     public $ui = false;
 
-    /** @var array List of element CSS classes. */
+    /** @var list List of element CSS classes. */
     public array $class = [];
 
     /** @var array Map of element CSS styles. */
@@ -144,7 +144,8 @@ public function setModel(Model $model): void
     /**
      * Sets source of the View.
      *
-     * @param array $fields Limit model to particular fields
+     * @param array $data
+     * @param list             $fields Limit model to particular fields
      *
      * @phpstan-assert !null $this->model
      */
@@ -276,8 +277,8 @@ public function getExecutorFactory(): ExecutorFactory
      * In addition to adding a child object, sets up it's template
      * and associate it's output with the region in our template.
      *
-     * @param AbstractView      $object
-     * @param string|array|null $region
+     * @param AbstractView             $object
+     * @param string|array|null $region
      */
     #[\Override]
     public function add($object, $region = null): AbstractView
@@ -371,7 +372,7 @@ public function set($content)
      * Multiple CSS classes can also be added if passed as space separated
      * string or array of class names.
      *
-     * @param string|array $class
+     * @param string|list $class
      *
      * @return $this
      */
@@ -388,14 +389,14 @@ public function addClass($class)
     /**
      * Remove one or several CSS classes from the element.
      *
-     * @param string|array $class
+     * @param string|list $class
      *
      * @return $this
      */
     public function removeClass($class)
     {
         $classArr = explode(' ', is_array($class) ? implode(' ', $class) : $class);
-        $this->class = array_diff($this->class, $classArr);
+        $this->class = array_values(array_diff($this->class, $classArr));
 
         return $this;
     }
@@ -460,7 +461,7 @@ public function setAttr($name, $value = null)
     /**
      * Remove attribute.
      *
-     * @param string|array $name
+     * @param string|list $name
      *
      * @return $this
      */
@@ -481,7 +482,7 @@ public function removeAttr($name)
 
     // {{{ Sticky URLs
 
-    /** @var array stickyGet arguments */
+    /** @var array stickyGet arguments */
     public $stickyArgs = [];
 
     /**
@@ -506,6 +507,8 @@ public function jsUrl($page = []): string
 
     /**
      * Get sticky arguments defined by the view and parents (including API).
+     *
+     * @return array
      */
     protected function _getStickyArgs(): array
     {
@@ -680,6 +683,8 @@ public function renderToHtml(): string
 
     /**
      * Render View using JSON format.
+     *
+     * @return array
      */
     public function renderToJsonArr(): array
     {
@@ -796,7 +801,7 @@ public function js($when = false, $action = null, $selector = null): ?JsExpressi
      * as Vue.component() method.
      *
      * @param string                $component           The component name
-     * @param array                 $initData            The component properties passed as the initData prop.
+     * @param array  $initData            The component properties passed as the initData prop.
      *                                                   This is the initial data pass to your main component via the initData bind property
      *                                                   of the vue component instance created via the vueService.
      * @param JsExpressionable|null $componentDefinition component definition object
@@ -833,6 +838,8 @@ public function vue($component, $initData = [], $componentDefinition = null, $se
      * Note: In order to make sure your event is unique within atk, you can
      * use the view name in it.
      *    $this->jsEmitEvent($this->name . '-my-event', $data)
+     *
+     * @param array $eventData
      */
     public function jsEmitEvent(string $eventName, array $eventData = []): JsChain
     {
@@ -842,16 +849,19 @@ public function jsEmitEvent(string $eventName, array $eventData = []): JsChain
     /**
      * Get Local and Session web storage associated with this view.
      * Web storage can be retrieved using a $view->jsReload() request.
+     *
+     * @return array{local: mixed, session: mixed}
      */
     public function jsGetStoreData(): array
     {
-        $data = [];
-        $data['local'] = $this->getApp()->decodeJson(
-            $this->getApp()->tryGetRequestQueryParam($this->name . '_local_store') ?? $this->getApp()->tryGetRequestPostParam($this->name . '_local_store') ?? 'null'
-        );
-        $data['session'] = $this->getApp()->decodeJson(
-            $this->getApp()->tryGetRequestQueryParam($this->name . '_session_store') ?? $this->getApp()->tryGetRequestPostParam($this->name . '_session_store') ?? 'null'
-        );
+        $data = [
+            'local' => $this->getApp()->decodeJson(
+                $this->getApp()->tryGetRequestQueryParam($this->name . '_local_store') ?? $this->getApp()->tryGetRequestPostParam($this->name . '_local_store') ?? 'null'
+            ),
+            'session' => $this->getApp()->decodeJson(
+                $this->getApp()->tryGetRequestQueryParam($this->name . '_session_store') ?? $this->getApp()->tryGetRequestPostParam($this->name . '_session_store') ?? 'null'
+            ),
+        ];
 
         return $data;
     }
@@ -876,6 +886,8 @@ public function jsClearStoreData(bool $useSession = false): JsExpressionable
      *  $v->jsAddStoreData(['args' => ['path' => '/'], 'fields' => ['name' => 'test']]]);
      *
      *  Final store value will be: ['args' => ['path' => '/'], 'fields' => ['name' => 'test']];
+     *
+     * @param array $data
      */
     public function jsAddStoreData(array $data, bool $useSession = false): JsExpressionable
     {
@@ -887,9 +899,9 @@ public function jsAddStoreData(array $data, bool $useSession = false): JsExpress
     /**
      * Returns JS for reloading View.
      *
-     * @param array                 $args
-     * @param JsExpressionable|null $afterSuccess
-     * @param array  $apiConfig
+     * @param array $args
+     * @param JsExpressionable|null                      $afterSuccess
+     * @param array                       $apiConfig
      *
      * @return JsReload
      */
@@ -926,7 +938,8 @@ public function jsReload($args = [], $afterSuccess = null, array $apiConfig = []
      *
      * @param string                                                                                                                                                                                       $event    JavaScript event
      * @param ($action is object ? string : ($action is null ? string : never)|JsExpressionable|JsCallback|JsCallbackSetClosure|array{JsCallbackSetClosure}|UserAction\ExecutorInterface|Model\UserAction) $selector Optional jQuery-style selector
-     * @param ($selector is string|null ? JsExpressionable|JsCallback|JsCallbackSetClosure|array{JsCallbackSetClosure}|UserAction\ExecutorInterface|Model\UserAction : array)                              $action   code to execute
+     * @param ($selector is string|null ? JsExpressionable|JsCallback|JsCallbackSetClosure|array{JsCallbackSetClosure}|UserAction\ExecutorInterface|Model\UserAction : array)           $action   code to execute
+     * @param array                                                                                                                                                                     $defaults
      *
      * @return ($selector is string|null ? ($action is null ? Jquery : null) : ($action is array|null ? Jquery : null))
      */
diff --git a/src/VirtualPage.php b/src/VirtualPage.php
index 024c28a148..721d055362 100644
--- a/src/VirtualPage.php
+++ b/src/VirtualPage.php
@@ -39,7 +39,7 @@ protected function init(): void
      * Set callback function of virtual page.
      *
      * @param \Closure($this, mixed, mixed, mixed, mixed, mixed, mixed, mixed, mixed, mixed, mixed): void $fx
-     * @param array                                                                                       $fxArgs
+     * @param list                                                                                 $fxArgs
      */
     #[\Override]
     public function set($fx = null, $fxArgs = [])
diff --git a/src/Wizard.php b/src/Wizard.php
index 67659ed957..19d6990fd1 100644
--- a/src/Wizard.php
+++ b/src/Wizard.php
@@ -16,10 +16,10 @@ class Wizard extends View
     /** @var string Get argument for this wizard. */
     public $urlTrigger;
 
-    /** @var array List of steps. */
+    /** @var list */
     public array $steps = [];
 
-    /** @var int Current step. */
+    /** @var int */
     public $currentStep;
 
     /** @var Button Button for going to previous step. */
@@ -76,8 +76,8 @@ protected function getUrl(int $step): string
     /**
      * Adds step to the wizard.
      *
-     * @param string|array|WizardStep $name
-     * @param \Closure($this): void   $fx
+     * @param string|array|WizardStep $name
+     * @param \Closure($this): void          $fx
      *
      * @return WizardStep
      */
diff --git a/tests/AppTest.php b/tests/AppTest.php
index ef26a5d32d..8b28e80933 100644
--- a/tests/AppTest.php
+++ b/tests/AppTest.php
@@ -123,6 +123,9 @@ public function testEmptyRequestPathException(): void
         $this->createApp(['request' => $request]);
     }
 
+    /**
+     * @return iterable>
+     */
     public static function provideUrlCases(): iterable
     {
         foreach (['/', '/page.html', '/d/', '/0/index.php'] as $requestPage) {
diff --git a/tests/CallbackTest.php b/tests/CallbackTest.php
index d055e3e232..d056817348 100644
--- a/tests/CallbackTest.php
+++ b/tests/CallbackTest.php
@@ -33,6 +33,9 @@ class CallbackTest extends TestCase
 
     protected static string $regexHtml = '~^\s*$~s';
 
+    /**
+     * @param array<0|string, mixed> $seed
+     */
     protected function createApp(array $seed = []): App
     {
         if (!isset($seed[0])) {
diff --git a/tests/DemosHttpTest.php b/tests/DemosHttpTest.php
index 9cb13dc52c..8b42c4bb95 100644
--- a/tests/DemosHttpTest.php
+++ b/tests/DemosHttpTest.php
@@ -175,6 +175,9 @@ public function testDemoLateOutputError(string $urlTrigger, string $expectedOutp
         self::assertSame($expectedOutput, $response->getBody()->getContents());
     }
 
+    /**
+     * @return iterable>
+     */
     public static function provideDemoLateOutputErrorCases(): iterable
     {
         $hOutput = "\n" . '!! FATAL UI ERROR: Headers already sent, more headers cannot be set at this stage !!' . "\n";
diff --git a/tests/DemosTest.php b/tests/DemosTest.php
index bd2d6ee2e6..bc37e929c4 100644
--- a/tests/DemosTest.php
+++ b/tests/DemosTest.php
@@ -31,6 +31,7 @@ class DemosTest extends TestCase
     protected const ROOT_DIR = __DIR__ . '/..';
     protected const DEMOS_DIR = self::ROOT_DIR . '/demos';
 
+    /** @var array */
     private static array $_serverSuperglobalBackup;
 
     private static ?Persistence $_db = null;
@@ -199,6 +200,9 @@ protected function getClient(): Client
         return new Client(['base_uri' => 'http://localhost/', 'handler' => $handler]);
     }
 
+    /**
+     * @param array $options
+     */
     protected function getResponseFromRequest(string $path, array $options = []): ResponseInterface
     {
         try {
@@ -222,6 +226,9 @@ public static function getResponseBodySummary(ResponseInterface $response): stri
         }
     }
 
+    /**
+     * @param array $options
+     */
     protected function getResponseFromRequest5xx(string $path, array $options = []): ResponseInterface
     {
         try {
@@ -244,6 +251,9 @@ protected function getPathWithAppVars(string $path): string
         return 'demos/' . $path;
     }
 
+    /**
+     * @return iterable>
+     */
     public static function provideDemosStatusAndHtmlResponseCases(): iterable
     {
         $excludeDirs = ['_demo-data', '_includes'];
@@ -314,6 +324,9 @@ public function testDemoResponseError(): void
         self::assertStringContainsString('Property for specified object is not defined', $response->getBody()->getContents());
     }
 
+    /**
+     * @return iterable>
+     */
     public static function provideDemoGetCases(): iterable
     {
         yield ['others/sticky.php?xx=YEY'];
@@ -385,6 +398,9 @@ public function testWizard(): void
         self::assertMatchesRegularExpression(self::$regexHtml, $response->getBody()->getContents());
     }
 
+    /**
+     * @return iterable>
+     */
     public static function provideDemoJsonResponseCases(): iterable
     {
         // simple reload
@@ -427,6 +443,9 @@ public function testDemoJsonResponse(string $path, ?string $expectedExceptionMes
         }
     }
 
+    /**
+     * @return iterable>
+     */
     public static function provideDemoSseResponseCases(): iterable
     {
         yield ['_unit-test/sse.php?' . Callback::URL_QUERY_TRIGGER_PREFIX . 'see_test=ajax&' . Callback::URL_QUERY_TARGET . '=1'];
@@ -455,6 +474,9 @@ public function testDemoSseResponse(string $path): void
         self::assertMatchesRegularExpression(self::$regexSse, $response->getBody()->getContents());
     }
 
+    /**
+     * @return iterable>
+     */
     public static function provideDemoJsonResponsePostCases(): iterable
     {
         yield [
@@ -464,6 +486,8 @@ public static function provideDemoJsonResponsePostCases(): iterable
     }
 
     /**
+     * @param array $postData
+     *
      * @dataProvider provideDemoJsonResponsePostCases
      */
     #[DataProvider('provideDemoJsonResponsePostCases')]
@@ -475,6 +499,8 @@ public function testDemoJsonResponsePost(string $path, array $postData): void
     }
 
     /**
+     * @param array $options
+     *
      * @dataProvider provideDemoCallbackErrorCases
      *
      * @slowThreshold 1500
@@ -497,6 +523,9 @@ public function testDemoCallbackError(string $path, string $expectedExceptionMes
         self::assertStringContainsString($expectedExceptionMessage, $responseBodyStr);
     }
 
+    /**
+     * @return iterable>
+     */
     public static function provideDemoCallbackErrorCases(): iterable
     {
         yield [
diff --git a/tests/FormTest.php b/tests/FormTest.php
index f70394296c..95216acb06 100644
--- a/tests/FormTest.php
+++ b/tests/FormTest.php
@@ -47,6 +47,9 @@ public function testAddControlAlreadyExistsException(): void
         $form->addControl('foo');
     }
 
+    /**
+     * @param array $postData
+     */
     protected function triggerFormSubmit(ServerRequestInterface $request, Form $form, array $postData): ServerRequestInterface
     {
         $request = $this->triggerCallback($request, $form->cb);
@@ -62,6 +65,7 @@ protected function triggerFormSubmit(ServerRequestInterface $request, Form $form
 
     /**
      * @param \Closure(App): Form    $createFormFx
+     * @param array  $postData
      * @param \Closure(Model): void  $submitFx
      * @param \Closure(string): void $checkExpectedErrorsFx
      */
@@ -421,7 +425,7 @@ public function testUploadNoDeleteCallbackException(): void
 
 class AppFormTestMock extends App
 {
-    /** @var string|array */
+    /** @var string|array */
     public $output;
 
     #[\Override]
diff --git a/tests/PaginatorTest.php b/tests/PaginatorTest.php
index b596fc0e19..006b4945e0 100644
--- a/tests/PaginatorTest.php
+++ b/tests/PaginatorTest.php
@@ -10,6 +10,9 @@
 
 class PaginatorTest extends TestCase
 {
+    /**
+     * @return iterable>
+     */
     public static function providePaginatorCases(): iterable
     {
         yield [1, 1, 1, [1]];
@@ -33,6 +36,8 @@ public static function providePaginatorCases(): iterable
     }
 
     /**
+     * @param list $expected
+     *
      * @dataProvider providePaginatorCases
      */
     #[DataProvider('providePaginatorCases')]
diff --git a/tests/PersistenceUiTest.php b/tests/PersistenceUiTest.php
index 5875b73827..cccf64d28a 100644
--- a/tests/PersistenceUiTest.php
+++ b/tests/PersistenceUiTest.php
@@ -12,7 +12,9 @@
 class PersistenceUiTest extends TestCase
 {
     /**
-     * @param mixed $phpValue
+     * @param array $persistenceSeed
+     * @param array $fieldSeed
+     * @param mixed                $phpValue
      *
      * @dataProvider provideTypecastBidirectionalCases
      * @dataProvider provideTypecastLoadOnlyCases
@@ -58,6 +60,9 @@ public function testTypecast(array $persistenceSeed, array $fieldSeed, $phpValue
         }
     }
 
+    /**
+     * @return iterable>
+     */
     public static function provideTypecastBidirectionalCases(): iterable
     {
         $fixSpaceToNbspFx = static fn (string $v) => str_replace(' ', "\u{00a0}", $v);
@@ -145,6 +150,9 @@ public static function provideTypecastBidirectionalCases(): iterable
         }
     }
 
+    /**
+     * @return iterable>
+     */
     public static function provideTypecastLoadOnlyCases(): iterable
     {
         foreach (['smallint', 'integer', 'bigint', 'float', 'boolean', 'date', 'time', 'datetime', 'atk4_money'] as $type) {
@@ -206,7 +214,8 @@ public static function provideTypecastLoadOnlyCases(): iterable
     }
 
     /**
-     * @param mixed $phpValue
+     * @param array $fieldSeed
+     * @param mixed                $phpValue
      *
      * @dataProvider provideAttributeTypecastCases
      */
@@ -230,6 +239,9 @@ public function testAttributeTypecast(array $fieldSeed, $phpValue, ?string $uiVa
         self::assertSame($uiValue, $savedUiValue);
     }
 
+    /**
+     * @return iterable>
+     */
     public static function provideAttributeTypecastCases(): iterable
     {
         yield [['type' => 'integer'], 1, '1'];
diff --git a/tests/TagTest.php b/tests/TagTest.php
index 07ff4194d2..8da14cb08e 100644
--- a/tests/TagTest.php
+++ b/tests/TagTest.php
@@ -11,7 +11,7 @@
 class TagTest extends TestCase
 {
     /**
-     * @param array{0: string, 1?: array<0|string, string|bool>, 2?: string|array|null} $args
+     * @param array{0: string, 1?: array<0|string, string|bool>, 2?: string|list|null} $args
      */
     public static function assertTagRender(string $expectedHtml, array $args): void
     {
diff --git a/tests/ViewTest.php b/tests/ViewTest.php
index 173bb87c2d..c479cec28c 100644
--- a/tests/ViewTest.php
+++ b/tests/ViewTest.php
@@ -158,7 +158,7 @@ public function testSetNotClosureError(string $class): void
     }
 
     /**
-     * @return iterable}>
+     * @return iterable>
      */
     public static function provideSetNotClosureErrorCases(): iterable
     {