diff --git a/docs/50_Forms/Input.md b/docs/50_Forms/Input.md
index 90dc83d57e3f3b152c8021acaec16d16954a0c5a..b60d6c9e59759260158c6f5b067057698d3c1ced 100644
--- a/docs/50_Forms/Input.md
+++ b/docs/50_Forms/Input.md
@@ -31,21 +31,22 @@ Content:
 
 Key      | Description
 ---      | ---
+hint     | optional: Hint text above form field
 label    | label in front of the input element
 name     | name attribute for sending form data
 value    | value of the input field/ visible text; for checkbox and radio: the data to send when sending a form
 
-### Example
+### Examples
 
 #### Simple text input field
 
 ```php
-$renderAdminLTE->getFormInput(array (
+$renderAdminLTE->getFormInput([
   'label' => 'Enter firstname',
   'type' => 'text',
   'name' => 'firstname',
   'value' => '',
-));
+]);
 ```
 
 You get a label, an input field wrapped in a ``<div class="form-group row">``.
@@ -72,8 +73,6 @@ With using append and prepend keys you can create gray boxes on left and right.
 For these input types you can use multiple elements.
 You must wrap a bunch of input elements into ``<div class="form-group row">`` "manually".
 
-
-
 ```php
 echo '<div class="form-group">'
   . $renderAdminLTE->getFormInput([
@@ -91,3 +90,60 @@ echo '<div class="form-group">'
   .'</div>'
   ;
 ```
+
+#### Simple range slider
+
+A simple slider:
+
+```php
+$renderAdminLTE->getFormInput([
+  'tag' => 'input', 
+  'type' => 'range', // <-----------
+  'min' => 0, 
+  'max' => 3, 
+  'step' => 1, 
+  'label' => 'Select 0..6',
+]);
+```
+
+#### Range with labels
+
+To add labels you need a datalist for the values and the labels to show, eg
+
+```html
+<datalist id="datalist-range">
+  <option value="0" label="no risc"></option>
+  <option value="1" label="1"></option>
+  <option value="2" label="2"></option>
+  <option value="3" label="medium"></option>
+  <option value="4" label="4"></option>
+  <option value="5" label="5"></option>
+  <option value="6" label="critical"></option>
+</datalist>
+```
+
+The id you ned to reference in the key "datalist":
+
+```php
+$renderAdminLTE->getFormInput([
+  'tag' => 'input', 
+  'type' => 'range', 
+  'min' => 0, 
+  'max' => 6, 
+  'step' => 1, 
+  'label' => 'Select 0..6',
+  'datalist' => 'datalist-range', // <-----------
+]);
+```
+
+For the datalist you need to extend your css:
+
+```css
+datalist {
+  display: flex;
+  flex-direction: column;
+  justify-content: space-between;
+  writing-mode: vertical-lr;
+  width: 100%;
+}
+```
diff --git a/docs/50_Forms/Select.md b/docs/50_Forms/Select.md
index 415a7f312baf18ebb6511bff41847cc410531e1a..e83f6623f2a6a18e6a8e37fe1faa8b063a36c3f9 100644
--- a/docs/50_Forms/Select.md
+++ b/docs/50_Forms/Select.md
@@ -26,6 +26,7 @@ Styling for select tag:
 
 Key      | Description
 ---      | ---
+bootstrap-select | optional: use bootstrap-select pugin with live search (you need to load the plugin in your page - see example below)
 class    | optional: additional css classes
 size     | optional: visible option lines
 
@@ -33,6 +34,7 @@ Content:
 
 Key      | Description
 ---      | ---
+hint     | optional: Hint text above form field
 name     | name attribute for sending form data
 value    | value of the input field/ visible text; for checkbox and radio: the data to send when sending a form
 
@@ -41,8 +43,7 @@ value    | value of the input field/ visible text; for checkbox and radio: the d
 #### Simple select box
 
 ```php
-$renderAdminLTE->getFormSelect(array
-(
+$renderAdminLTE->getFormSelect([
     'label' => 'Select contact',
     'name' => 'contact',
     'tag' => 'select',
@@ -53,7 +54,7 @@ $renderAdminLTE->getFormSelect(array
             ['value' => '2', 'label' => 'Dick', 'selected' => 1 ],
             ['value' => '3', 'label' => 'Harry'],
     ],
-));
+]);
 ```
 
 You get a label, an select box wrapped in a ``<div class="form-group row">``.
@@ -73,3 +74,31 @@ You get a label, an select box wrapped in a ``<div class="form-group row">``.
     </div>
 </div>
 ```
+
+#### Select box with search field
+
+We added support for the plugin **bootstrap-select**.
+Get its files from the website and put it into a vendor directory.
+
+Website: <https://developer.snapappointments.com/bootstrap-select/>
+
+In your html header section add its css and javascript:
+
+```html
+    <!-- bootstrap-select -->
+    <link rel="stylesheet" href="../vendor/bootstrap-select/1.13.18/css/bootstrap-select.min.css">
+    <script src="../vendor/bootstrap-select/1.13.18/js/bootstrap-select.min.js"></script>
+```
+
+In your select box add ``'bootstrap-select' => 1,`` :
+
+```php
+$renderAdminLTE->getFormSelect([
+    'label' => 'Select contact',
+    'name' => 'contact',
+    'tag' => 'select',
+    'size' => 1,
+    'bootstrap-select' => 1, // <---------- 
+    'options' => [ ... ],
+]);
+```
diff --git a/docs/50_Forms/Textarea.md b/docs/50_Forms/Textarea.md
index 69f28d32ddadaca76e02f04ec2b3f7cf49f1477a..34b8de4874566dc8b86ebd640ca710d568d1c5df 100644
--- a/docs/50_Forms/Textarea.md
+++ b/docs/50_Forms/Textarea.md
@@ -29,6 +29,7 @@ Content:
 
 Key      | Description
 ---      | ---
+hint     | optional: Hint text above form field
 label    | label in front of the Textarea element
 name     | name attribute for sending form data
 value    | value of the textarea; visible text
@@ -40,11 +41,11 @@ value    | value of the textarea; visible text
 You get a label and a textare wrapped in a ``<div class="form-group row">``.
 
 ```php
-$renderAdminLTE->getFormTextarea(array (
+$renderAdminLTE->getFormTextarea([
   'label' => 'Enter text',
   'name' => 'textdata',
   'value' => 'Here is some text...',
-));
+]);
 ```
 
 #### Html editor
@@ -72,7 +73,7 @@ By adding ``'type' => 'html'`` an html editor will be rendered by adding a class
 
 ```php
 $renderAdminLTE->getFormTextarea(array (
-  'type' => 'html',
+  'type' => 'html', // <---------- 
   'label' => 'Enter text',
   'name' => 'textdata',
   'value' => 'Here is some text...',
diff --git a/public_html/classes/htmlelements.class.php b/public_html/classes/htmlelements.class.php
index 91943c7c97d4a3226b6a2c457496ed85b08ef447..18d58b69e46f14477046359e68e5a6d732a85f52 100755
--- a/public_html/classes/htmlelements.class.php
+++ b/public_html/classes/htmlelements.class.php
@@ -15,26 +15,39 @@
  *    - icon  - will be added as <i class="[icon value]"></i> to the label
  * 
  * @author Axel
+ * 
+ * 2024-07-04  <axel.hahn@unibe.ch>  added type declarations; update php docs
  */
-class htmlelements {
+class htmlelements
+{
 
     /**
      * set of auto generated icon prefixes
-     * @var type 
+     * @var array
+     */
+    var $_aIcons = array(
+        // 'fa-'=>'fa ',
+    );
+
+    /**
+     * label of an html tag (pseudo attribute)
+     * @var string
      */
-    var $_aIcons=array(
-            // 'fa-'=>'fa ',
-        );
-    
     var $_sLabel = '';
+
+    /**
+     * hash of attributes and values of an html tag
+     * @var array
+     */
     var $_aAttributes = array();
-    
+
 
     // ----------------------------------------------------------------------
     // CONSTRUCTOR
     // ----------------------------------------------------------------------
-    
-    public function __construct() {
+
+    public function __construct()
+    {
         return true;
     }
 
@@ -43,25 +56,26 @@ class htmlelements {
     // PRIVATE FUNCTIONS 
     // 
     // ----------------------------------------------------------------------
-    
-    
+
+
     /**
      * generate html attibutes with all internal attributes key -> values
      * @return string
      */
-    protected function _addAttributes() {
+    protected function _addAttributes(): string
+    {
         $sReturn = '';
         foreach ($this->_aAttributes as $sAttr => $sValue) {
-            if(is_array($sValue)){
-                echo "ERROR: an html tag was defined with array in attribute [$sAttr]:<br><pre>".print_r($this->_aAttributes, 1)."</pre>";
+            if (is_array($sValue)) {
+                echo "ERROR: an html tag was defined with array in attribute [$sAttr]:<br><pre>" . print_r($this->_aAttributes, 1) . "</pre>";
             }
-            $sReturn .= ' '.$sAttr . '="' . $sValue . '"';
-            
+            $sReturn .= ' ' . $sAttr . '="' . $sValue . '"';
+
         }
         return $sReturn;
     }
-    
-    
+
+
     /**
      * internal helper: fetch all attributes from key-value hash; 
      * Specialties here:
@@ -71,17 +85,18 @@ class htmlelements {
      * @param array $aAttributes
      * @return boolean
      */
-    protected function _setAttributes($aAttributes){
-        $this->_sLabel='';
-        if(isset($aAttributes['icon']) && $aAttributes['icon']){
-            $this->_sLabel.=$this->getIcon($aAttributes['icon']);
+    protected function _setAttributes(array $aAttributes): bool
+    {
+        $this->_sLabel = '';
+        if (isset($aAttributes['icon']) && $aAttributes['icon']) {
+            $this->_sLabel .= $this->getIcon($aAttributes['icon']);
             unset($aAttributes['icon']);
         }
-        if(isset($aAttributes['label']) && $aAttributes['label']){
+        if (isset($aAttributes['label']) && $aAttributes['label']) {
             $this->_sLabel .= $aAttributes['label'];
             unset($aAttributes['label']);
         }
-        $this->_aAttributes=$aAttributes;
+        $this->_aAttributes = $aAttributes;
         return true;
     }
 
@@ -91,7 +106,7 @@ class htmlelements {
     // HTML GENERIC
     // 
     // ----------------------------------------------------------------------
-    
+
     /**
      * generic function to get html code for a single tag 
      * 
@@ -100,12 +115,13 @@ class htmlelements {
      * @param boolean  $bCloseTag     optional: set false if tag has no closing tag (= ending with "/>")
      * @return type
      */
-    public function getTag($sTag, $aAttributes, $bCloseTag=true){
+    public function getTag(string $sTag, array $aAttributes, bool $bCloseTag = true): string
+    {
         $sTpl = $bCloseTag ? "<$sTag%s>%s</$sTag>" : "<$sTag %s/>%s";
         $this->_setAttributes($aAttributes);
         return sprintf($sTpl, $this->_addAttributes(), $this->_sLabel);
     }
-    
+
     // ----------------------------------------------------------------------
     // 
     // PUBLIC FUNCTIONS
@@ -114,28 +130,28 @@ class htmlelements {
     // ----------------------------------------------------------------------
 
     /**
-     * helper detect prefix of a string add prefix of a framework
+     * get html code for an icon
+     * includes a helper detect prefix of a string add prefix of a framework
      * i.e. value "fa-close" detects font awesome and adds "fa " as prefix
      * 
-     * @param string $sIconclass
-     * @return boolean
+     * @param string $sIconclass  name of the icon
+     * @return string
      */
-    public function getIcon($sIconclass=false){
-        if(!$sIconclass){
+    public function getIcon(string $sIconclass = ''): string
+    {
+        if (!$sIconclass) {
             return '';
         }
-        $sPrefix='';
-        foreach ($this->_aIcons as $sPrefix =>$add) {
-            if (strpos($sIconclass, $sPrefix)===0){
-                $sPrefix=$add;
+        $sPrefix = '';
+        foreach ($this->_aIcons as $sPrefix => $add) {
+            if (strpos($sIconclass, $sPrefix) === 0) {
+                $sPrefix = $add;
                 continue;
             }
         }
-        // do not use this .. it overrides internal attribute vars
-        // return $this->getTag('i', array('class'=>$sPrefix.$sIconclass));
-        return '<i class="'.$sPrefix.$sIconclass.'"></i> ';
+        return '<i class="' . $sPrefix . $sIconclass . '"></i> ';
     }
-   
+
 
     // ----------------------------------------------------------------------
     // 
@@ -150,7 +166,8 @@ class htmlelements {
      * @param array $aAttributes  attributes of the select tag
      * @return string
      */
-    public function getFormInput($aAttributes){
+    public function getFormInput($aAttributes)
+    {
         $sTpl = '<input %s/>';
         $this->_setAttributes($aAttributes);
         return sprintf($sTpl, $this->_addAttributes());
@@ -161,7 +178,8 @@ class htmlelements {
      * @param array $aAttributes  attributes of the option tag
      * @return string
      */
-    public function getFormOption($aAttributes){
+    public function getFormOption(array $aAttributes): string
+    {
         $sTpl = '<option %s>%s</option>';
         $this->_setAttributes($aAttributes);
         return sprintf($sTpl, $this->_addAttributes(), $this->_sLabel);
@@ -173,50 +191,57 @@ class htmlelements {
      * @param array $aOptions     array for all option fields
      * @return string
      */
-    public function getFormSelect($aAttributes, $aOptions=array()){
+    public function getFormSelect(array $aAttributes, array $aOptions = array())
+    {
         // $sTpl = '<select %s>%s</select>';
 
-        if(!count($aOptions)){
+        if (!count($aOptions)) {
             return false;
         }
-        $sOptions='';
-        foreach($aOptions as $aOptionAttributes){
+        $sOptions = '';
+        foreach ($aOptions as $aOptionAttributes) {
             // $sOptions.=$this->getFormOption($aOptionAttributes);
-            $sOptions.=$this->getTag('option', $aOptionAttributes);
+            $sOptions .= $this->getTag('option', $aOptionAttributes);
         }
-        $aAttributes['label']=$sOptions;
+        $aAttributes['label'] = $sOptions;
         return $this->getTag('select', $aAttributes);
-        /*
-        $this->_setAttributes($aAttributes);
-        return sprintf($sTpl, $this->_addAttributes(), $sOptions);
-         * 
-         */
     }
 
-    public function getTable($aHead, $aBody, $aTableAttributes=array()){
-        $sReturn='';
-        $sTdata='';
-        $sThead='';
+
+    /**
+     * Generates an HTML table based on the provided header and body arrays.
+     *
+     * @param array $aHead An array of strings representing the table headers.
+     * @param array $aBody A 2-dimensional array of strings representing the table body rows and cells.
+     * @param array $aTableAttributes An optional array of attributes to be applied to the table element.
+     * @return string The HTML code for the generated table.
+     */
+    public function getTable(array $aHead, array $aBody, array $aTableAttributes = []): string
+    {
+        $sReturn = '';
+        $sTdata = '';
+        $sThead = '';
         $sTpl = '<table %s>'
-                . '<thead><tr>%s</tr></thead>'
-                . '<tbody>%s</tbody>'
-                . '</table>';
-        
-        foreach($aHead as $sTh){
-            $sThead.='<th>'.$sTh.'</th>';
+            . '<thead><tr>%s</tr></thead>'
+            . '<tbody>%s</tbody>'
+            . '</table>';
+
+        foreach ($aHead as $sTh) {
+            $sThead .= '<th>' . $sTh . '</th>';
         }
-        foreach($aBody as $aTr){
-            $sTdata.='<tr>';
-            foreach($aTr as $sTd){
-                $sTdata.='<td>'.$sTd.'</td>';
+        foreach ($aBody as $aTr) {
+            $sTdata .= '<tr>';
+            foreach ($aTr as $sTd) {
+                $sTdata .= '<td>' . $sTd . '</td>';
             }
-            $sTdata.='</tr>';
+            $sTdata .= '</tr>';
         }
         $this->_setAttributes($aTableAttributes);
-        return sprintf($sTpl, 
-                $this->_addAttributes(), 
-                $sThead,
-                $sTdata
-                );
+        return sprintf(
+            $sTpl,
+            $this->_addAttributes(),
+            $sThead,
+            $sTdata
+        );
     }
 }
diff --git a/public_html/classes/render-adminlte.class.php b/public_html/classes/render-adminlte.class.php
index 1035af9dac0f6e7adc4704f6e9cca0fa36851aca..83cf626c624afc23bc6237422c52be5c2b01d7b4 100755
--- a/public_html/classes/render-adminlte.class.php
+++ b/public_html/classes/render-adminlte.class.php
@@ -1,156 +1,171 @@
 <?php
 require_once 'htmlelements.class.php';
 /**
- * ======================================================================
+ * ______________________________________________________________________
+ * 
+ *     _  __  __  _    
+ *    | ||  \/  || |__     Institute for Medical Education
+ *    |_||_|\/|_||____|    University of Bern
+ * 
+ * ______________________________________________________________________
  * 
  * RENDERER FOR ADNINLTE template https://adminlte.io
- * DOCS: https://adminlte.io/docs/3.2/
- *       https://adminlte.io/themes/v3/index3.html
+ * its docs: https://adminlte.io/docs/3.2/
+ *           https://adminlte.io/themes/v3/index3.html
+ * 
+ * This is a php class to render
+ * - grid layout
+ * - navigation
+ * - widgets, components and forms
  * 
+ * DOCS: https://os-docs.iml.unibe.ch/adminlte-renderer/
  * ----------------------------------------------------------------------
  * 2023-09-11  <axel.hahn@unibe.ch>  add shadows on card + callout
  * 2023-09-27  <axel.hahn@unibe.ch>  add form input fields
  * 2023-11-17  <axel.hahn@unibe.ch>  add tabbed content; "=" renders hamburger item
  * 2024-05-03  <axel.hahn@unibe.ch>  add line in sidebar menu; add getFormSelect
+ * 2024-05-10  <axel.hahn@unibe.ch>  add support for bootstrap-select in getFormSelect
+ * 2024-05-18  <axel.hahn@unibe.ch>  add variable types
+ * 2024-07-04  <axel.hahn@unibe.ch>  added type declarations
  * ======================================================================
- *
- * @author Axel
  */
-class renderadminlte {
+class renderadminlte
+{
 
-    var $aPresets=[
+    protected array $aPresets = [
 
-        'bgcolor'=>[
-            'description'=>'background colors',
-            'group'=>'styling',
-            'values'=>[
+        'bgcolor' => [
+            'description' => 'background colors',
+            'group' => 'styling',
+            'values' => [
                 // https://adminlte.io/themes/v3/pages/UI/general.html
-                ''=>'no value',
-                'indigo'=>'indigo',
-                'lightblue'=>'',
-                'navy'=>'',
-                'purple'=>'',
-                'fuchsia'=>'',
-                'pink'=>'',
-                'maroon'=>'',
-                'orange'=>'',
-                'lime'=>'',
-                'teal'=>'',
-                'olive'=>'',
-        
-                'black'=>'black',
-                'dark'=>'dark gray',
-                'gray'=>'gray', 
-                'light'=>'light gray', 
+                '' => 'no value',
+                'indigo' => 'indigo',
+                'lightblue' => '',
+                'navy' => '',
+                'purple' => '',
+                'fuchsia' => '',
+                'pink' => '',
+                'maroon' => '',
+                'orange' => '',
+                'lime' => '',
+                'teal' => '',
+                'olive' => '',
+
+                'black' => 'black',
+                'dark' => 'dark gray',
+                'gray' => 'gray',
+                'light' => 'light gray',
             ]
         ],
-    
-        'type'=>[
-            'description'=>'type or status like info/ warning/ danger to define a color',
-            'group'=>'styling',
-            'values'=>[
-                ''=>'no value',
-                'danger'=>'red',
-                'info'=>'aqua',
-                'primary'=>'blue',
-                'secondary'=>'gray',
-                'success'=>'green',
-                'warning'=>'yellow',
-                'dark'=>'dark gray',
-                'gray'=>'gray', 
+
+        'type' => [
+            'description' => 'type or status like info/ warning/ danger to define a color',
+            'group' => 'styling',
+            'values' => [
+                '' => 'no value',
+                'danger' => 'red',
+                'info' => 'aqua',
+                'primary' => 'blue',
+                'secondary' => 'gray',
+                'success' => 'green',
+                'warning' => 'yellow',
+                'dark' => 'dark gray',
+                'gray' => 'gray',
             ]
         ],
-        'shadow'=>[
-            'description'=>'use a shadow',
-            'group'=>'styling',
-            'values'=>[
-                ''=>'no value', 
-                'none'=>'none',
-                'small'=>'small', 
-                'regular'=>'regular',
-                'large'=>'large'
+        'shadow' => [
+            'description' => 'use a shadow',
+            'group' => 'styling',
+            'values' => [
+                '' => 'no value',
+                'none' => 'none',
+                'small' => 'small',
+                'regular' => 'regular',
+                'large' => 'large'
             ]
         ],
-        'size'=>[
-            'description'=>'set a size',
-            'group'=>'styling',
-            'values'=>[
-                ''=>'no value',
-                'lg'=>'',
-                'sm'=>'',
-                'xs'=>'',
-                'flat'=>'',
+        'size' => [
+            'description' => 'set a size',
+            'group' => 'styling',
+            'values' => [
+                '' => 'no value',
+                'lg' => '',
+                'sm' => '',
+                'xs' => '',
+                'flat' => '',
             ]
         ],
-        'variant'=>[
-            'description'=>'coloring style',
-            'group'=>'styling',
-            'values'=>[
-                ''=>'no value',
-                'outline'=>'small stripe on top',
-                'solid'=>'full filled widget',
-                'gradient'=>'full filled with gradient',
+        'variant' => [
+            'description' => 'coloring style',
+            'group' => 'styling',
+            'values' => [
+                '' => 'no value',
+                'outline' => 'small stripe on top',
+                'solid' => 'full filled widget',
+                'gradient' => 'full filled with gradient',
             ]
         ],
-        'visibility'=>[
-            'description'=>'',
-            'group'=>'customizing',
-            'values'=>[
-                ''=>'no value', 
-                '0'=>'hide', 
-                '1'=>'show',
+        'visibility' => [
+            'description' => '',
+            'group' => 'customizing',
+            'values' => [
+                '' => 'no value',
+                '0' => 'hide',
+                '1' => 'show',
             ]
         ],
         // for keys: state
-        'windowstate'=>[
-            'description'=>'state of a resizable widget',
-            'group'=>'customizing',
-            'values'=>[
-                ''=>'no value', 
-                'collapsed'=>'header only', 
-                'maximized'=>'full window',
+        'windowstate' => [
+            'description' => 'state of a resizable widget',
+            'group' => 'customizing',
+            'values' => [
+                '' => 'no value',
+                'collapsed' => 'header only',
+                'maximized' => 'full window',
             ]
         ],
         // for keys: dismissable
-        'yesno'=>[
-            'description'=>'',
-            'group'=>'customizing',
-            'values'=>[
-                ''=>'no value', 
-                '0'=>'no', 
-                '1'=>'yes',
+        'yesno' => [
+            'description' => '',
+            'group' => 'customizing',
+            'values' => [
+                '' => 'no value',
+                '0' => 'no',
+                '1' => 'yes',
             ]
         ],
     ];
 
-    var $_aValueMappings=[
-        'shadow'=>[
-            'default'  => '',
-            'none'     => 'shadow-none',
-            'small'    => 'shadow-small',
-            'regular'  => 'shadow',
-            'large'    => 'shadow-lg',
+    protected array $_aValueMappings = [
+        'shadow' => [
+            'default' => '',
+            'none' => 'shadow-none',
+            'small' => 'shadow-small',
+            'regular' => 'shadow',
+            'large' => 'shadow-lg',
         ]
     ];
 
-    var $_aElements=[];
-    
+    protected array $_aElements = [];
+
     /**
-     * instance of htmlelements
+     * instance of htmlelements object
      * @var object
      */
-    var $_oHtml=false;
-    
-    
+    protected object $_oHtml;
+
+
     // ----------------------------------------------------------------------
     // 
     // CONSTRUCTOR
     // 
     // ----------------------------------------------------------------------
-    public function __construct() {
-        $this->_oHtml=new htmlelements();
+    public function __construct()
+    {
+        $this->_oHtml = new htmlelements();
         $this->_initElements();
-        return true;
+        // return true;
     }
 
     // ----------------------------------------------------------------------
@@ -158,343 +173,380 @@ class renderadminlte {
     // PRIVATE FUNCTIONS 
     // 
     // ----------------------------------------------------------------------
-    
+
     /**
      * used in cosntructor
      * initialize all element definitions
+     * @return void
      */
-    protected function _initElements(){
-        $this->_aElements=[
+    protected function _initElements(): void
+    {
+        $this->_aElements = [
 
             // ------------------------------------------------------------
-            'alert'=>[
-                'label'=>'Alert',
-                'description'=>'Colored box with title and a text',
-                'method'=>'getAlert',
-        
-                'params'=>[
-                    'type'        => ['select'=>$this->aPresets['type'],     'example_value'=>'warning'],
-                    'dismissible' => ['select'=>$this->aPresets['yesno'],    'example_value'=>''],
-                    'class'       => [
-                        'group'=>'styling', 
-                        'description'=>'optional: css classes', 
-                        'example_value'=>''
+            'alert' => [
+                'label' => 'Alert',
+                'description' => 'Colored box with title and a text',
+                'method' => 'getAlert',
+
+                'params' => [
+                    'type' => ['select' => $this->aPresets['type'], 'example_value' => 'warning'],
+                    'dismissible' => ['select' => $this->aPresets['yesno'], 'example_value' => ''],
+                    'class' => [
+                        'group' => 'styling',
+                        'description' => 'optional: css classes',
+                        'example_value' => ''
                     ],
-                    'title'       => [
-                        'description'=>'Title in a bit bigger font', 
-                        'group'=>'content',
-                        'example_value'=>'Alert title'
+                    'title' => [
+                        'description' => 'Title in a bit bigger font',
+                        'group' => 'content',
+                        'example_value' => 'Alert title'
                     ],
-                    'text'        => [
-                        'description'=>'Message text', 
-                        'group'=>'content',
-                        'example_value'=>'I am a message. Read me, please.'
+                    'text' => [
+                        'description' => 'Message text',
+                        'group' => 'content',
+                        'example_value' => 'I am a message. Read me, please.'
                     ],
                 ]
             ],
             // ------------------------------------------------------------
-            'badge'=>[
-                'label'=>'Badge',
-                'description'=>'Tiny additional info; mostly as counter',
-                'method'=>'getBadge',
-        
-                'params'=>[
-                    'type'        => ['select'=>$this->aPresets['type'],     'example_value'=>'danger'],
-                    'bgcolor'     => ['select'=>$this->aPresets['bgcolor'],  'example_value'=>''],
-                    'class'       => [
-                        'group'=>'styling', 
-                        'description'=>'optional: css classes', 
-                        'example_value'=>''
+            'badge' => [
+                'label' => 'Badge',
+                'description' => 'Tiny additional info; mostly as counter',
+                'method' => 'getBadge',
+
+                'params' => [
+                    'type' => ['select' => $this->aPresets['type'], 'example_value' => 'danger'],
+                    'bgcolor' => ['select' => $this->aPresets['bgcolor'], 'example_value' => ''],
+                    'class' => [
+                        'group' => 'styling',
+                        'description' => 'optional: css classes',
+                        'example_value' => ''
                     ],
-                    'id'          => [
-                        'group'=>'customizing', 
-                        'description'=>'optional: id attribute', 
-                        'example_value'=>''
+                    'id' => [
+                        'group' => 'customizing',
+                        'description' => 'optional: id attribute',
+                        'example_value' => ''
                     ],
-                    'title'       => [
-                        'group'=>'content', 
-                        'description'=>'optional: title attribute for mouseover', 
-                        'example_value'=>'Errors: 5'
+                    'title' => [
+                        'group' => 'content',
+                        'description' => 'optional: title attribute for mouseover',
+                        'example_value' => 'Errors: 5'
                     ],
-                    'text'        => [
-                        'group'=>'content', 
-                        'description'=>'Text or value in the badge', 
-                        'example_value'=>'5'
+                    'text' => [
+                        'group' => 'content',
+                        'description' => 'Text or value in the badge',
+                        'example_value' => '5'
                     ],
                 ]
             ],
             // ------------------------------------------------------------
-            'button'=>[
-                'label'=>'Button',
-                'description'=>'Buttons<br>In this component you can add other parmeter keys too - these will be added as attributes in the button tag.',
-                'method'=>'getButton',
-        
-                'params'=>[
-                    'type'        => ['select'=>$this->aPresets['type'],     'example_value'=>'primary'],
-                    'size'        => ['select'=>$this->aPresets['size'],     'example_value'=>''],
-                    'class'       => [
-                        'group'=>'styling', 
-                        'description'=>'optional: css classes', 
-                        'example_value'=>''
+            'button' => [
+                'label' => 'Button',
+                'description' => 'Buttons<br>In this component you can add other parmeter keys too - these will be added as attributes in the button tag.',
+                'method' => 'getButton',
+
+                'params' => [
+                    'type' => ['select' => $this->aPresets['type'], 'example_value' => 'primary'],
+                    'size' => ['select' => $this->aPresets['size'], 'example_value' => ''],
+                    'class' => [
+                        'group' => 'styling',
+                        'description' => 'optional: css classes',
+                        'example_value' => ''
                     ],
-                    'text'        => [
-                        'group'=>'content', 
-                        'description'=>'Text/ html code on the button', 
-                        'example_value'=>'Click me'
+                    'text' => [
+                        'group' => 'content',
+                        'description' => 'Text/ html code on the button',
+                        'example_value' => 'Click me'
                     ],
                 ]
             ],
             // ------------------------------------------------------------
-            'callout'=>[
-                'label'=>'Callout',
-                'description'=>'Kind of infobox',
-                'method'=>'getCallout',
-        
-                'params'=>[
-                    'type'        => ['select'=>$this->aPresets['type'],     'example_value'=>'danger'],
-                    'shadow'      => ['select'=>$this->aPresets['shadow'],   'example_value'=>''],
-                    'class'       => [
-                        'group'=>'styling', 
-                        'description'=>'optional: css classes', 
-                        'example_value'=>''
+            'callout' => [
+                'label' => 'Callout',
+                'description' => 'Kind of infobox',
+                'method' => 'getCallout',
+
+                'params' => [
+                    'type' => ['select' => $this->aPresets['type'], 'example_value' => 'danger'],
+                    'shadow' => ['select' => $this->aPresets['shadow'], 'example_value' => ''],
+                    'class' => [
+                        'group' => 'styling',
+                        'description' => 'optional: css classes',
+                        'example_value' => ''
                     ],
-                    'title'       => [
-                        'group'=>'content', 
-                        'description'=>'Title in a bit bigger font', 
-                        'example_value'=>'I am a callout'
+                    'title' => [
+                        'group' => 'content',
+                        'description' => 'Title in a bit bigger font',
+                        'example_value' => 'I am a callout'
                     ],
-                    'text'        => [
-                        'group'=>'content',
-                        'description'=>'Message text', 
-                        'example_value'=>'Here is some description to whatever.'
+                    'text' => [
+                        'group' => 'content',
+                        'description' => 'Message text',
+                        'example_value' => 'Here is some description to whatever.'
                     ],
                 ]
             ],
             // ------------------------------------------------------------
-            'card'=>[
-                'label'=>'Card',
-                'description'=>'Content box with header, text, footer',
-                'method'=>'getCard',
-        
-                'params'=>[
-                    'type'        => ['select'=>$this->aPresets['type'],     'example_value'=>'primary'],
-                    'variant'     => ['select'=>$this->aPresets['variant'],  'example_value'=>'outline'],
-                    'shadow'      => ['select'=>$this->aPresets['shadow'],   'example_value'=>''],
-                    'class'       => [
-                        'group'=>'styling', 
-                        'description'=>'optional: css classes', 
-                        'example_value'=>''
+            'card' => [
+                'label' => 'Card',
+                'description' => 'Content box with header, text, footer',
+                'method' => 'getCard',
+
+                'params' => [
+                    'type' => ['select' => $this->aPresets['type'], 'example_value' => 'primary'],
+                    'variant' => ['select' => $this->aPresets['variant'], 'example_value' => 'outline'],
+                    'shadow' => ['select' => $this->aPresets['shadow'], 'example_value' => ''],
+                    'class' => [
+                        'group' => 'styling',
+                        'description' => 'optional: css classes',
+                        'example_value' => ''
                     ],
-                    'state'       => [
-                        'group'=>'customizing', 
-                        'select'=>$this->aPresets['windowstate'], 
-                        'example_value'=>''
+                    'state' => [
+                        'group' => 'customizing',
+                        'select' => $this->aPresets['windowstate'],
+                        'example_value' => ''
                     ],
-        
-                    'tb-collapse' => ['description'=>'show minus symbol as collapse button', 'select'=>$this->aPresets['visibility'], 'example_value'=>''],
-                    'tb-expand'   => ['description'=>'show plus symbol to expand card', 'select'=>$this->aPresets['visibility'], 'example_value'=>''],
-                    'tb-maximize' => ['description'=>'show maximize button for fullscreen', 'select'=>$this->aPresets['visibility'], 'example_value'=>''],
-                    'tb-minimize' => ['description'=>'show minimize button to minimize', 'select'=>$this->aPresets['visibility'], 'example_value'=>''],
-                    'tb-remove'   => ['description'=>'show cross symbol to remove card', 'select'=>$this->aPresets['visibility'], 'example_value'=>''],
-        
-                    'title'       => [
-                        'group'=>'content', 
-                        'description'=>'Title in the top row', 
-                        'example_value'=>'I am a card'
+
+                    'tb-collapse' => ['description' => 'show minus symbol as collapse button', 'select' => $this->aPresets['visibility'], 'example_value' => ''],
+                    'tb-expand' => ['description' => 'show plus symbol to expand card', 'select' => $this->aPresets['visibility'], 'example_value' => ''],
+                    'tb-maximize' => ['description' => 'show maximize button for fullscreen', 'select' => $this->aPresets['visibility'], 'example_value' => ''],
+                    'tb-minimize' => ['description' => 'show minimize button to minimize', 'select' => $this->aPresets['visibility'], 'example_value' => ''],
+                    'tb-remove' => ['description' => 'show cross symbol to remove card', 'select' => $this->aPresets['visibility'], 'example_value' => ''],
+
+                    'title' => [
+                        'group' => 'content',
+                        'description' => 'Title in the top row',
+                        'example_value' => 'I am a card'
                     ],
-                    'tools'       => [
-                        'group'=>'content', 
-                        'description'=>'Html code for the top right', 
-                        'example_value'=>''
+                    'tools' => [
+                        'group' => 'content',
+                        'description' => 'Html code for the top right',
+                        'example_value' => ''
                     ],
-                    'text'        => [
-                        'group'=>'content', 
-                        'description'=>'Main content', 
-                        'example_value'=>'Here is some beautiful content.'
+                    'text' => [
+                        'group' => 'content',
+                        'description' => 'Main content',
+                        'example_value' => 'Here is some beautiful content.'
                     ],
-                    'footer'      => [
-                        'group'=>'content', 
-                        'description'=>'optional: footer content', 
-                        'example_value'=>'Footer'
+                    'footer' => [
+                        'group' => 'content',
+                        'description' => 'optional: footer content',
+                        'example_value' => 'Footer'
                     ],
                 ]
             ],
             // ------------------------------------------------------------
-            'infobox'=>[
-                'label'=>'Info box',
-                'description'=>'Box with icon to highlight a single value; optional with a progress bar',
-                'method'=>'getInfobox',
-        
-                'params'=>[
-                    'type'=>['select'=>$this->aPresets['type'],     'example_value'=>''],
-                    'iconbg'=>['select'=>$this->aPresets['type'],   'example_value'=>'info'],
-                    'shadow'=>['select'=>$this->aPresets['shadow'], 'example_value'=>''],
-                    'class'       => [
-                        'group'=>'styling', 
-                        'description'=>'optional: css classes', 
-                        'example_value'=>''
+            'infobox' => [
+                'label' => 'Info box',
+                'description' => 'Box with icon to highlight a single value; optional with a progress bar',
+                'method' => 'getInfobox',
+
+                'params' => [
+                    'type' => ['select' => $this->aPresets['type'], 'example_value' => ''],
+                    'iconbg' => ['select' => $this->aPresets['type'], 'example_value' => 'info'],
+                    'shadow' => ['select' => $this->aPresets['shadow'], 'example_value' => ''],
+                    'class' => [
+                        'group' => 'styling',
+                        'description' => 'optional: css classes',
+                        'example_value' => ''
                     ],
-                    'icon'=>[
-                        'group'=>'content', 
-                        'description'=>'css class for an icon', 
-                        'example_value'=>'fa-regular fa-thumbs-up'
+                    'icon' => [
+                        'group' => 'content',
+                        'description' => 'css class for an icon',
+                        'example_value' => 'fa-regular fa-thumbs-up'
                     ],
-                    'text'=>[
-                        'group'=>'content', 
-                        'description'=>'short information text', 
-                        'example_value'=>'Likes'
+                    'text' => [
+                        'group' => 'content',
+                        'description' => 'short information text',
+                        'example_value' => 'Likes'
                     ],
-                    'number'=>[
-                        'group'=>'content', 
-                        'description'=>'a number to highlight', 
-                        'example_value'=>"41,410"
+                    'number' => [
+                        'group' => 'content',
+                        'description' => 'a number to highlight',
+                        'example_value' => "41,410"
                     ],
-                    'progressvalue'=>[
-                        'group'=>'content', 
-                        'description'=>'optional: progress value 0..100 to draw a progress bar', 
-                        'example_value'=>70
+                    'progressvalue' => [
+                        'group' => 'content',
+                        'description' => 'optional: progress value 0..100 to draw a progress bar',
+                        'example_value' => 70
                     ],
-                    'progresstext'=>[
-                        'group'=>'content', 
-                        'description'=>'optional: text below progress bar', 
-                        'example_value'=>'70% Increase in 30 Days'
+                    'progresstext' => [
+                        'group' => 'content',
+                        'description' => 'optional: text below progress bar',
+                        'example_value' => '70% Increase in 30 Days'
                     ]
                 ]
             ],
             // ------------------------------------------------------------
-            'smallbox'=>[
-                'label'=>'Small box',
-                'description'=>'Solid colored box to highlight a single value; optional with a link',
-                'method'=>'getSmallbox',
-        
-                'params'=>[
-                    'type'=>['select'=>$this->aPresets['type'],     'example_value'=>'info'],
-                    'shadow'=>['select'=>$this->aPresets['shadow'], 'example_value'=>''],
-                    'class'       => [
-                        'group'=>'styling', 
-                        'description'=>'optional: css classes', 
-                        'example_value'=>''
+            'smallbox' => [
+                'label' => 'Small box',
+                'description' => 'Solid colored box to highlight a single value; optional with a link',
+                'method' => 'getSmallbox',
+
+                'params' => [
+                    'type' => ['select' => $this->aPresets['type'], 'example_value' => 'info'],
+                    'shadow' => ['select' => $this->aPresets['shadow'], 'example_value' => ''],
+                    'class' => [
+                        'group' => 'styling',
+                        'description' => 'optional: css classes',
+                        'example_value' => ''
                     ],
-                    'icon'=>['group'=>'content', 'description'=>'css class for an icon', 'example_value'=>'fa-solid fa-shopping-cart'],
-        
-                    'text'=>['group'=>'content', 'description'=>'short information text', 'example_value'=>'New orders'],
-                    'number'=>['group'=>'content', 'description'=>'a number to highlight', 'example_value'=>"150"],
-                    'url'=>['group'=>'content', 'description'=>'optional: url to set a link on the bottom', 'example_value'=>'#'],
-                    'linktext'=>['group'=>'content', 'description'=>'used if a url was given: linked text', 'example_value'=>'More info']
+                    'icon' => ['group' => 'content', 'description' => 'css class for an icon', 'example_value' => 'fa-solid fa-shopping-cart'],
+
+                    'text' => ['group' => 'content', 'description' => 'short information text', 'example_value' => 'New orders'],
+                    'number' => ['group' => 'content', 'description' => 'a number to highlight', 'example_value' => "150"],
+                    'url' => ['group' => 'content', 'description' => 'optional: url to set a link on the bottom', 'example_value' => '#'],
+                    'linktext' => ['group' => 'content', 'description' => 'used if a url was given: linked text', 'example_value' => 'More info']
                 ]
             ],
             // ------------------------------------------------------------
-            'input'=>[
-                'label'=>'Form: input',
-                'description'=>'Input form fiels',
-                'method'=>'getFormInput',
-        
-                'params'=>[
-                    'label'       => [
-                        'group'=>'styling', 
-                        'description'=>'label for the input field', 
-                        'example_value'=>'Enter something'
+            'input' => [
+                'label' => 'Form: input',
+                'description' => 'Input form fiels',
+                'method' => 'getFormInput',
+
+                'params' => [
+                    'label' => [
+                        'group' => 'styling',
+                        'description' => 'label for the input field',
+                        'example_value' => 'Enter something'
                     ],
-                    'type'=>['select'=> [
-                            'description'=>'type or input field',
-                            'group'=>'styling',
-                            'values'=>[
-                                'text'=>'text',
-                                'password'=>'password',
-                                'email'=>'email',
-                                'hidden'=>'hidden',
-
-                                'button'=>'button',
-                                'checkbox'=>'checkbox',
-                                'color'=>'color',
-                                'date'=>'date',
-                                'datetime-local'=>'datetime-local',
-                                'email'=>'email',
-                                'file'=>'file',
-                                'hidden'=>'hidden',
-                                'image'=>'image',
-                                'month'=>'month',
-                                'number'=>'number',
-                                'password'=>'password',
-                                'radio'=>'radio',
-                                'range'=>'range',
-                                'reset'=>'reset',
-                                'search'=>'search',
-                                'submit'=>'submit',
-                                'tel'=>'tel',
-                                'text'=>'text',
-                                'time'=>'time',
-                                'url'=>'url',
-                                'week'=>'week',
-                                ]
-                            ], 
-                            'example_value'=>'text'
+                    'type' => [
+                        'select' => [
+                            'description' => 'type or input field',
+                            'group' => 'styling',
+                            'values' => [
+
+                                'button' => 'button',
+                                'checkbox' => 'checkbox',
+                                'color' => 'color',
+                                'date' => 'date',
+                                'datetime-local' => 'datetime-local',
+                                'email' => 'email',
+                                'file' => 'file',
+                                'hidden' => 'hidden',
+                                'image' => 'image',
+                                'month' => 'month',
+                                'number' => 'number',
+                                'password' => 'password',
+                                'radio' => 'radio',
+                                'range' => 'range',
+                                'reset' => 'reset',
+                                'search' => 'search',
+                                'submit' => 'submit',
+                                'tel' => 'tel',
+                                'text' => 'text',
+                                'time' => 'time',
+                                'url' => 'url',
+                                'week' => 'week',
+                            ]
+                        ],
+                        'example_value' => 'text'
                     ],
-                    'class'       => [
-                        'group'=>'styling', 
-                        'description'=>'optional: css classes', 
-                        'example_value'=>'myclass'
+                    'class' => [
+                        'group' => 'styling',
+                        'description' => 'optional: css classes',
+                        'example_value' => 'myclass'
                     ],
-                    'prepend'       => [
-                        'group'=>'styling', 
-                        'description'=>'optional: content on input start', 
-                        'example_value'=>''
+                    'prepend' => [
+                        'group' => 'styling',
+                        'description' => 'optional: content on input start',
+                        'example_value' => ''
                     ],
-                    'append'       => [
-                        'group'=>'styling', 
-                        'description'=>'optional: content on input end', 
-                        'example_value'=>''
+                    'append' => [
+                        'group' => 'styling',
+                        'description' => 'optional: content on input end',
+                        'example_value' => ''
                     ],
-                    'name'       => [
-                        'group'=>'content', 
-                        'description'=>'name attribute', 
-                        'example_value'=>'firstname'
+                    'name' => [
+                        'group' => 'content',
+                        'description' => 'name attribute',
+                        'example_value' => 'firstname'
                     ],
                     'value' => [
-                        'group'=>'content', 
-                        'description'=>'Value', 
-                        'example_value'=>'Jack'
+                        'group' => 'content',
+                        'description' => 'Value',
+                        'example_value' => 'Jack'
                     ],
                 ]
             ],
             // ------------------------------------------------------------
-            'textarea'=>[
-                'label'=>'Form: textarea',
-                'description'=>'textarea or html editor',
-                'method'=>'getFormTextarea',
-        
-                'params'=>[
-                    'label'       => [
-                        'group'=>'styling', 
-                        'description'=>'label for the input field', 
-                        'example_value'=>'Enter text'
+            // WIP
+            'select' => [
+                'label' => 'Form: select',
+                'description' => 'Select box',
+                'method' => 'getFormSelect',
+
+                'params' => [
+                    'label' => [
+                        'group' => 'styling',
+                        'description' => 'label for the select field',
+                        'example_value' => 'Enter text'
                     ],
-                    'type'=>['select'=> [
-                            'description'=>'type or input field',
-                            'group'=>'styling',
-                            'values'=>[
-                                ''=>'text',
-                                'html'=>'html editor',
-                                ]
-                            ], 
+                    'bootstrap-select' => [
+                        'select' => [
+                            'description' => 'Enable bootstrap-select plugin',
+                            'group' => 'styling',
+                            'values' => [
+                                '0' => 'no',
+                                '1' => 'yes',
+                            ]
+                        ]
                     ],
-                    'class'       => [
-                        'group'=>'styling', 
-                        'description'=>'optional: css classes', 
-                        'example_value'=>'myclass'
+                    'class' => [
+                        'group' => 'styling',
+                        'description' => 'optional: css classes',
+                        'example_value' => 'myclass'
                     ],
-                    'name'       => [
-                        'group'=>'content', 
-                        'description'=>'name attribute', 
-                        'example_value'=>'textdata'
+                    'options' => [
+                        'example_value' => [
+                            ["value" => "1", "label" => "one"],
+                            ["value" => "2", "label" => "two"],
+                            ["value" => "3", "label" => "three"],
+                        ],
+                    ]
+                ],
+            ],
+            // ------------------------------------------------------------
+            'textarea' => [
+                'label' => 'Form: textarea',
+                'description' => 'textarea or html editor',
+                'method' => 'getFormTextarea',
+
+                'params' => [
+                    'label' => [
+                        'group' => 'styling',
+                        'description' => 'label for the input field',
+                        'example_value' => 'Enter text'
+                    ],
+                    'type' => [
+                        'select' => [
+                            'description' => 'type or input field',
+                            'group' => 'styling',
+                            'values' => [
+                                '' => 'text',
+                                'html' => 'html editor',
+                            ]
+                        ],
+                    ],
+                    'class' => [
+                        'group' => 'styling',
+                        'description' => 'optional: css classes',
+                        'example_value' => 'myclass'
+                    ],
+                    'name' => [
+                        'group' => 'content',
+                        'description' => 'name attribute',
+                        'example_value' => 'textdata'
                     ],
                     'value' => [
-                        'group'=>'content', 
-                        'description'=>'Value', 
-                        'example_value'=>'Here is some text...'
+                        'group' => 'content',
+                        'description' => 'Value',
+                        'example_value' => 'Here is some text...'
                     ],
                 ]
-            ],            
+            ],
         ];
     }
     /**
@@ -503,10 +555,12 @@ class renderadminlte {
      * @param  array   $aAttributes  array of its attributes
      * @param  string  $sContent     content between opening and closing tag
      * @param  bool    $bClosetag    flag: write a closing tag or not? default: true
+     * @return string
      */
-    protected function _tag($sTag, $aAttributes, $sContent=false, $bClosetag=true){
-        if ($sContent){
-            $aAttributes['label']=(isset($aAttributes['label']) ? $aAttributes['label'] : '') . $sContent;
+    protected function _tag(string $sTag, array $aAttributes, string $sContent = '', bool $bClosetag = true): string
+    {
+        if ($sContent) {
+            $aAttributes['label'] = (isset($aAttributes['label']) ? $aAttributes['label'] : '') . $sContent;
         }
         return $this->_oHtml->getTag($sTag, $aAttributes, $bClosetag);
     }
@@ -520,25 +574,29 @@ class renderadminlte {
      * render a page by using template 
      * @param  string  $stemplate  html template with placeholders
      * @param  array   $aReplace   key = what to replace .. value = new value
+     * @return string
      */
-    public function render($sTemplate, $aReplace){
+    public function render(string $sTemplate, array $aReplace): string
+    {
         return str_replace(
             array_keys($aReplace),
             array_values($aReplace),
             $sTemplate
         );
     }
-    
 
     /**
      * add a wrapper: wrap some content into a tag
      * 
+     * @param  string  $sTag      name of html tag
+     * @param  array   $aOptions  array of its attributes
      * @param  string  $sContent  html content inside
      * @return string
      */
-    public function addWrapper($sTag, $aOptions, $sContent){
-        $aOptions['label']=$sContent;
-        return $this->_tag($sTag, $aOptions)."\n";
+    public function addWrapper(string $sTag, array $aOptions, string $sContent): string
+    {
+        $aOptions['label'] = $sContent;
+        return $this->_tag($sTag, $aOptions) . PHP_EOL;
     }
 
     // ----------------------------------------------------------------------
@@ -547,7 +605,6 @@ class renderadminlte {
     // 
     // ----------------------------------------------------------------------
 
-
     /** 
      * get a single navigation item on top bar
      * 
@@ -555,80 +612,93 @@ class renderadminlte {
      * @param  integer  $iLevel  Menu level; 1=top bar; 2=pupup menu with subitems
      * @return string
      */
-    public function getNavItem($aLink, $iLevel=1){
+    public function getNavItem(array $aLink, int $iLevel = 1): string
+    {
         static $iCounter;
-        if(!isset($iCounter)){
-            $iCounter=0;
+        if (!isset($iCounter)) {
+            $iCounter = 0;
         }
-        
+
         switch ($aLink['label']) {
             // special menu entry: horizontal bar (label is "-")
-            case '-': return '<div class="dropdown-divider"></div>'; break;
+            case '-':
+                return '<div class="dropdown-divider"></div>';
+                break;
 
             // special menu entry: hamburger menu item (label is "=")
-            case '=': return '<li class="nav-item"><a class="nav-link" data-widget="pushmenu" href="#" role="button"><i class="fas fa-bars"></i></a></li>'; break;
+            case '=':
+                return '<li class="nav-item"><a class="nav-link" data-widget="pushmenu" href="#" role="button"><i class="fas fa-bars"></i></a></li>';
+                break;
 
             // special menu entry: hamburger menu item (label is "|")
             // requires css: .navbar-nav li.divider{border-left: 1px solid rgba(0,0,0,0.2);}
-            case '|': return '<li class="divider"></li>'; break;
+            case '|':
+                return '<li class="divider"></li>';
+                break;
         }
 
-        $aChildren=isset($aLink['children']) && is_array($aLink['children']) && count($aLink['children']) ? $aLink['children'] : false;
+        $aChildren = isset($aLink['children']) && is_array($aLink['children']) && count($aLink['children']) ? $aLink['children'] : false;
 
-        $aLink['class']='nav-link'
-            . (isset($aLink['class']) ? ' '.$aLink['class'] : '')
+        $aLink['class'] = 'nav-link'
+            . (isset($aLink['class']) ? ' ' . $aLink['class'] : '')
             . ($aChildren ? ' dropdown-toggle' : '')
-            ;
-        if($aChildren){
+        ;
+        if ($aChildren) {
             $iCounter++;
-            $sNavId="navbarDropdown".$iCounter;
-            $aLink=array_merge($aLink,[
-                'id'=>$sNavId,
-                'role'=>"button",
-                'data-toggle'=>"dropdown",
-                'aria-haspopup'=>"true",
-                'aria-expanded'=>"false",
+            $sNavId = "navbarDropdown" . $iCounter;
+            $aLink = array_merge($aLink, [
+                'id' => $sNavId,
+                'role' => "button",
+                'data-toggle' => "dropdown",
+                'aria-haspopup' => "true",
+                'aria-expanded' => "false",
             ]);
             unset($aLink['children']); // remove from html attributes to draw
         }
-        $sReturn=$this->_tag('a', $aLink)."\n";
-        if($aChildren){ 
+        $sReturn = $this->_tag('a', $aLink) . "\n";
+        if ($aChildren) {
             $iLevel++;
-            $sReturn.=$this->addWrapper(
-                    'div', 
-                    [ 
-                        'aria-labelledby'=> $sNavId,
-                        'class'=>'dropdown-menu'
-                    ], 
-                    $this->getNavItems($aChildren, $iLevel)
-                )."\n";
+            $sReturn .= $this->addWrapper(
+                'div',
+                [
+                    'aria-labelledby' => $sNavId,
+                    'class' => 'dropdown-menu'
+                ],
+                $this->getNavItems($aChildren, $iLevel)
+            ) . "\n";
             $iLevel--;
         }
-   
-        if($iLevel==1){
-            $sLiClass='nav-item'.($aChildren ? ' dropdown' : '');
-            $sReturn=$this->addWrapper(
-                'li', 
-                ['class'=>$sLiClass],
-                $sReturn 
+
+        if ($iLevel == 1) {
+            $sLiClass = 'nav-item' . ($aChildren ? ' dropdown' : '');
+            $sReturn = $this->addWrapper(
+                'li',
+                ['class' => $sLiClass],
+                $sReturn
             );
         }
         return $sReturn;
     }
+
     /** 
-     * get a navigation item for top bar
+     * get html code for navigation on top bar
      * 
+     * @param array $aLinks  array of navigation items
+     * @param int   $iLevel  current navigation level; default: 1
+     * @return string|bool
      */
-    public function getNavItems($aLinks, $iLevel=1){
-        $sReturn='';
-        if (!$aLinks || !is_array($aLinks) || !count($aLinks)){
+    public function getNavItems(array $aLinks, int $iLevel = 1): string|bool
+    {
+        $sReturn = '';
+        if (!$aLinks || !is_array($aLinks) || !count($aLinks)) {
             return false;
         }
-        foreach($aLinks as $aLink){
-            $sReturn.=$this->getNavItem($aLink, $iLevel);
+        foreach ($aLinks as $aLink) {
+            $sReturn .= $this->getNavItem($aLink, $iLevel);
         }
         return $sReturn;
     }
+
     /**
      * get a top left navigation for a top navigation bar
      * 
@@ -650,20 +720,23 @@ class renderadminlte {
      *     .'</nav>'
      * </code>
      * 
-     * @param  array  $aNavitems   array of navigation items/ tree
-     * @param  array  $aUlOptions  array of html attrubutes for wrapping UL tag
+     * @param  array  $aNavItems        array of navigation items/ tree
+     * @param  array  $aUlOptions       array of html attrubutes for wrapping UL tag
+     * @param  array  $aNavItemsRight   array of html attrubutes for wrapping UL tag
+     * @param  array  $aUlOptionsRight  array of html attrubutes for wrapping UL tag
      * @return string
      */
-    public function getTopNavigation($aNavItems, $aUlOptions=false, $aNavItemsRight=[], $aUlOptionsRight=false){
+    public function getTopNavigation(array $aNavItems, array $aUlOptions = [], array $aNavItemsRight = [], array $aUlOptionsRight = []): string
+    {
         // array_unshift($aNavItems, ['class'=>'nav-link', 'data-widget'=>'pushmenu', 'href'=>'#', 'role'=>'button', 'label'=>'<i class="fa-solid fa-bars"></i>']);
-        $aUlOptLeft=$aUlOptions ? $aUlOptions : ['class'=>'navbar-nav'];
-        $aUlOptRight=$aUlOptionsRight ? $aUlOptionsRight : ['class'=>'navbar-nav ml-auto'];
+        $aUlOptLeft = count($aUlOptions) ? $aUlOptions : ['class' => 'navbar-nav'];
+        $aUlOptRight = count($aUlOptionsRight) ? $aUlOptionsRight : ['class' => 'navbar-nav ml-auto'];
         return $this->addWrapper('ul', $aUlOptLeft, $this->getNavItems($aNavItems))
-            .(count($aNavItemsRight)
+            . (count($aNavItemsRight)
                 ? $this->addWrapper('ul', $aUlOptRight, $this->getNavItems($aNavItemsRight))
                 : ''
             )
-            ;
+        ;
     }
 
     // ----------------------------------------------------------------------
@@ -677,54 +750,64 @@ class renderadminlte {
      *   .nav-item hr{color: #505860; border-top: 1px solid; height: 1px; padding: 0; margin: 0; }
      * 
      * @param  array  $aLinks  list of link items
+     * @return string|bool
      */
-    public function getNavi2Items($aLinks){
-        $sReturn='';
-        if (!$aLinks || !is_array($aLinks) || !count($aLinks)){
+    public function getNavi2Items(array $aLinks): string|bool
+    {
+        $sReturn = '';
+        if (!$aLinks || !is_array($aLinks) || !count($aLinks)) {
             return false;
         }
-        
-        foreach($aLinks as $aLink){
 
-            if ($aLink['label']=='-') {
+        foreach ($aLinks as $aLink) {
+
+            if ($aLink['label'] == '-') {
                 // TODO: draw a nice line
-                $sReturn.='<li class="nav-item"><hr></li>';  
+                $sReturn .= '<li class="nav-item"><hr></li>';
                 continue;
             }
             // to render active or open links: 
-            $aLink['class']='nav-link' . (isset($aLink['class']) ? ' '.$aLink['class'] : '');
-
-            $aChildren=isset($aLink['children']) ? $aLink['children'] : false;
-            $aLiClass='nav-item' . ($aChildren && strstr($aLink['class'], 'active') ? ' menu-open' : '');
-            $sSubmenu='';
-            if($aChildren){
-                unset($aLink['children']);                
-                $aLink['label'].='<i class="right fa-solid fa-angle-left"></i>';
-                $sSubmenu.=$this->getSidebarNavigation($aChildren, ['class'=>'nav nav-treeview']);
+            $aLink['class'] = 'nav-link' . (isset($aLink['class']) ? ' ' . $aLink['class'] : '');
+
+            $aChildren = isset($aLink['children']) ? $aLink['children'] : false;
+            $aLiClass = 'nav-item' . ($aChildren && strstr($aLink['class'], 'active') ? ' menu-open' : '');
+            $sSubmenu = '';
+            if ($aChildren) {
+                unset($aLink['children']);
+                $aLink['label'] .= '<i class="right fa-solid fa-angle-left"></i>';
+                $sSubmenu .= $this->getSidebarNavigation($aChildren, ['class' => 'nav nav-treeview']);
             }
-            $aLink['label']=$this->addWrapper('p', [], $aLink['label']);
-            $sReturn.=$this->addWrapper(
-                'li', ['class'=>$aLiClass],
-                $this->_tag('a', $aLink).$sSubmenu
-            )."\n";
+            $aLink['label'] = $this->addWrapper('p', [], $aLink['label']);
+            $sReturn .= $this->addWrapper(
+                'li',
+                ['class' => $aLiClass],
+                $this->_tag('a', $aLink) . $sSubmenu
+            ) . "\n";
         }
         return $sReturn;
     }
 
     /**
+     * get html code for sidebar navigation
      * 
+     * @param  array  $aNavItems   navigation item
+     * @param  array  $aUlOptions  aatributes for UL tag
+     * @param string
      */
-    public function getSidebarNavigation($aNavItems, $aUlOptions=[
-            'class'=>'nav nav-pills nav-sidebar flex-column nav-flat_ nav-child-indent',
-            'data-widget'=>'treeview',
-            'role'=>'menu',
-            'data-accordion'=>'false'
-            ])
-    {
+    public function getSidebarNavigation(
+        array $aNavItems,
+        array $aUlOptions = [
+            'class' => 'nav nav-pills nav-sidebar flex-column nav-flat_ nav-child-indent',
+            'data-widget' => 'treeview',
+            'role' => 'menu',
+            'data-accordion' => 'false'
+        ]
+    ): string {
         return $this->addWrapper(
-                'ul', $aUlOptions, 
-                $this->getNavi2Items($aNavItems)
-            )."\n";
+            'ul',
+            $aUlOptions,
+            $this->getNavi2Items($aNavItems)
+        ) . "\n";
     }
 
     // ----------------------------------------------------------------------
@@ -732,15 +815,16 @@ class renderadminlte {
     // PUBLIC FUNCTIONS :: CONTENT - BASIC FUNCTIONS
     // 
     // ----------------------------------------------------------------------
-    
+
     /**
      * add page row
      * 
      * @param  string  $sContent  html content inside
      * @return string
      */
-    public function addRow($sContent){
-        return $this->addWrapper('div', ['class'=>'row'], $sContent);
+    public function addRow(string $sContent): string
+    {
+        return $this->addWrapper('div', ['class' => 'row'], $sContent);
     }
 
     /**
@@ -751,8 +835,9 @@ class renderadminlte {
      * @param  string   $sFloat    css value for float attribute; default=false
      * @return string
      */
-    public function addCol($sContent, $iCols=6, $sFloat=false){
-        return $this->addWrapper('div', ['class'=>'col-md-'.$iCols, 'style'=>'float:'.$sFloat], $sContent);
+    public function addCol(string $sContent, int $iCols = 6, string $sFloat = ''): string
+    {
+        return $this->addWrapper('div', ['class' => 'col-md-' . $iCols, 'style' => 'float:' . $sFloat], $sContent);
     }
 
     // ----------------------------------------------------------------------
@@ -761,49 +846,52 @@ class renderadminlte {
     // 
     // ----------------------------------------------------------------------
 
-
     /**
      * get a list of all defined components that can be rendered
-     * @param  {bool}  $bSendData  flag: send including subkeys of the hash; default: false (keys only)
-     * @return {array}
+     * @param   bool  $bSendData  flag: send including subkeys of the hash; default: false (keys only)
+     * @return  array
      */
-    public function getComponents($bSendData=false){
+    public function getComponents(bool $bSendData = false): array
+    {
         return $bSendData
             ? $this->_aElements
             : array_keys($this->_aElements)
         ;
     }
+
     /**
      * get data of a component
-     * @param  {string}  $sComponent  id of the component
-     * @return {array}
+     * @param  string  $sComponent  id of the component
+     * @return array|bool
      */
-    public function getComponent($sComponent){
-        if(!isset($this->_aElements[$sComponent])){
+    public function getComponent(string $sComponent): array|bool
+    {
+        if (!isset($this->_aElements[$sComponent])) {
             return false;
         }
-        $aReturn=array_merge(['id'=>$sComponent], $this->_aElements[$sComponent]);
+        $aReturn = array_merge(['id' => $sComponent], $this->_aElements[$sComponent]);
         unset($aReturn['params']);
         return $aReturn;
     }
 
     /**
      * get parameter keys of a component
-     * @param  {string}  $sComponent  id of the component
-     * @param  {bool}    $bSendData  flag: send including subkeys of the hash; default: false (keys only)
-     * @return {array}
+     * @param  string  $sComponent  id of the component
+     * @param  bool    $bSendData   flag: send including subkeys of the hash; default: false (keys only)
+     * @return array|bool
      */
-    public function getComponentParamkeys($sComponent, $bSendData=false){
-        if(!isset($this->_aElements[$sComponent])){
+    public function getComponentParamkeys(string $sComponent, bool $bSendData = false)
+    {
+        if (!isset($this->_aElements[$sComponent])) {
             return false;
         }
-        $aKeys=array_keys($this->_aElements[$sComponent]['params']);
-        if(!$bSendData){
+        $aKeys = array_keys($this->_aElements[$sComponent]['params']);
+        if (!$bSendData) {
             return $aKeys;
         }
-        $aReturn=[];
-        foreach($aKeys as $sKey){
-            $aReturn[$sKey]=$this->getComponentParamkey($sComponent, $sKey);
+        $aReturn = [];
+        foreach ($aKeys as $sKey) {
+            $aReturn[$sKey] = $this->getComponentParamkey($sComponent, $sKey);
         }
         // $aReturn=$this->_aElements[$sComponent]['params'];
         return $aReturn;
@@ -811,34 +899,36 @@ class renderadminlte {
 
     /**
      * get information a parameter keys of a component
-     * @param  {string}  $sComponent  id of the component
-     * @param  {string}  $sKey        key in the options array
-     * @return {array}
+     * @param  string  $sComponent  id of the component
+     * @param  string  $sKey        key in the options array
+     * @return array|bool
      */
-    public function getComponentParamkey($sComponent, $sKey){
-        if(!isset($this->_aElements[$sComponent]['params'][$sKey])){
+    public function getComponentParamkey(string $sComponent, string $sKey): array|bool
+    {
+        if (!isset($this->_aElements[$sComponent]['params'][$sKey])) {
             return false;
         }
-        $aReturn=$this->_aElements[$sComponent]['params'][$sKey];
+        $aReturn = $this->_aElements[$sComponent]['params'][$sKey];
         // get description from a preset
-        if(!isset($aReturn['description']) && isset($aReturn['select']['description'])){
-            $aReturn['description']=$aReturn['select']['description'];
+        if (!isset($aReturn['description']) && isset($aReturn['select']['description'])) {
+            $aReturn['description'] = $aReturn['select']['description'];
         }
-        if(!isset($aReturn['group']) && isset($aReturn['select']['group'])){
-            $aReturn['group']=$aReturn['select']['group'];
+        if (!isset($aReturn['group']) && isset($aReturn['select']['group'])) {
+            $aReturn['group'] = $aReturn['select']['group'];
         }
         return $aReturn;
     }
 
     /**
      * get a flat list of valid parameters for a key in a component
-     * @param  {string}  $sComponent  id of the component
-     * @param  {string}  $sKey        key in the options array
-     * @return {array}
+     * @param  string  $sComponent  id of the component
+     * @param  string  $sKey        key in the options array
+     * @return array|bool
      */
-    public function getValidParamValues($sComponent, $sKey){
-        $aOptionkey=$this->getComponentParamkey($sComponent, $sKey);
-        if(!$aOptionkey || !isset($aOptionkey['select']['values'])){
+    public function getValidParamValues(string $sComponent, string $sKey): array|bool
+    {
+        $aOptionkey = $this->getComponentParamkey($sComponent, $sKey);
+        if (!$aOptionkey || !isset($aOptionkey['select']['values'])) {
             return false;
         }
         return array_keys($aOptionkey['select']['values']);
@@ -851,43 +941,49 @@ class renderadminlte {
      * helper: add a css value with prefix
      * this handles option keys in get[COMPONENT] methods
      * if a value is set then this function returns a space + prefix (param 2) + value
-     * @param  {string}  $sValue   option value
-     * @param  {string}  $sPrefix  prefix in front of css value
-     * @return {string}
+     * @param  string  $sValue   option value
+     * @param  string  $sPrefix  prefix in front of css value
+     * @return string
      */
-    protected function _addClassValue($sValue, $sPrefix=''){
-        return $sValue ? ' '.$sPrefix.$sValue : '';
+    protected function _addClassValue(string $sValue, string $sPrefix = ''): string
+    {
+        return $sValue ? ' ' . $sPrefix . $sValue : '';
     }
 
     /**
      * helper function for get[COMPONENTNAME] methods:
-     * ensure that all wanted keys exist in an array. Non existing keys will be added with value false
+     * ensure that all wanted keys exist in an array. Non existing keys will 
+     * be added with value false
+     * 
+     * @param string $sComponent    id of the component
+     * @param array  $aOptions      hash with keys for all options
      * @return array
      */
-    protected function _ensureOptions($sComponent, $aOptions=[]){
+    protected function _ensureOptions(string $sComponent, array $aOptions = []): array
+    {
 
-        $aParams=$this->getComponentParamkeys($sComponent, 0);
-        if(!$aParams){
-            $aOptions['_infos'][]="Warning: no definition was found for component $sComponent.";
+        $aParams = $this->getComponentParamkeys($sComponent, 0);
+        if (!$aParams) {
+            $aOptions['_infos'][] = "Warning: no definition was found for component $sComponent.";
             return $aOptions;
         }
-        foreach ($aParams as $sKey){
-            if(!isset($aOptions) || !isset($aOptions[$sKey])){
-                $aOptions[$sKey]=false;
-                if(!isset($aOptions['_infos'])){
-                    $aOptions['_infos']=[];
+        foreach ($aParams as $sKey) {
+            if (!isset($aOptions) || !isset($aOptions[$sKey])) {
+                $aOptions[$sKey] = false;
+                if (!isset($aOptions['_infos'])) {
+                    $aOptions['_infos'] = [];
                 }
-                $aOptions['_infos'][]="added missing key: $sKey";
+                $aOptions['_infos'][] = "added missing key: $sKey";
             }
 
             // $aParamdata
-            $aValidvalues=$this->getValidParamValues($sComponent, $sKey);
-            if($aValidvalues){
-                if(array_search($aOptions[$sKey], $aValidvalues)===false){
-                    echo "ERROR: [".$sComponent."] value &quot;".$aOptions[$sKey]."&quot; is not a valid for param key [".$sKey."]; it must be one of ".implode("|", $aValidvalues).'<br>';
+            $aValidvalues = $this->getValidParamValues($sComponent, $sKey);
+            if ($aValidvalues) {
+                if (array_search($aOptions[$sKey], $aValidvalues) === false) {
+                    echo "ERROR: [" . $sComponent . "] value &quot;" . $aOptions[$sKey] . "&quot; is not a valid for param key [" . $sKey . "]; it must be one of " . implode("|", $aValidvalues) . '<br>';
                 }
             }
-    
+
             // $this->_checkValue($sKey, $aOptions[$sKey], __METHOD__);
         }
         // echo '<pre>' . print_r($aOptions, 1) . '</pre>';
@@ -903,35 +999,36 @@ class renderadminlte {
      * return a alert box      
      * https://adminlte.io/themes/v3/pages/UI/general.html
      * 
-     * @param type $aOptions  hash with keys for all options
+     * @param array $aOptions  hash with keys for all options
      *                          - type - one of [none]|danger|info|primary|success|warning
      *                          - dismissible - if dismissible - one of true|false; default: false
      *                          - title
      *                          - text
      * @return string
      */
-    public function getAlert($aOptions){
-        $aOptions=$this->_ensureOptions('alert', $aOptions);
-        $aAlertIcons=[
-            'danger'=>'icon fa-solid fa-ban',
-            'info'=>'icon fa-solid fa-info',
-            'warning'=>'icon fa-solid fa-exclamation-triangle',
-            'success'=>'icon fa-solid fa-check',
+    public function getAlert(array $aOptions): string
+    {
+        $aOptions = $this->_ensureOptions('alert', $aOptions);
+        $aAlertIcons = [
+            'danger' => 'icon fa-solid fa-ban',
+            'info' => 'icon fa-solid fa-info',
+            'warning' => 'icon fa-solid fa-exclamation-triangle',
+            'success' => 'icon fa-solid fa-check',
         ];
 
-        $aElement=[
-            'class'=>'alert'
+        $aElement = [
+            'class' => 'alert'
                 . $this->_addClassValue($aOptions['type'], 'alert-')
                 . $this->_addClassValue($aOptions['dismissible'], 'alert-')
-                ,
-            'label'=>''
+            ,
+            'label' => ''
                 . ($aOptions['dismissible'] ? '<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>' : '')
                 . $this->_tag('h5', [
-                    'label'=> ''
-                        .(isset($aAlertIcons[$aOptions['type']]) ? '<i class="'.$aAlertIcons[$aOptions['type']].'"></i> ' : '')
-                        .$aOptions['title']
-                    ])
-                .$aOptions['text']
+                    'label' => ''
+                        . (isset($aAlertIcons[$aOptions['type']]) ? '<i class="' . $aAlertIcons[$aOptions['type']] . '"></i> ' : '')
+                        . $aOptions['title']
+                ])
+                . $aOptions['text']
         ];
 
         return $this->_tag('div', $aElement);
@@ -953,20 +1050,22 @@ class renderadminlte {
      *                          - text    - visible text
      *                          - title   - optional: title attribute
      *                          - type    - one of [none]|danger|dark|info|primary|secondary|success|warning
+     * @return string
      */
-    public function getBadge($aOptions){
-        $aOptions=$this->_ensureOptions('badge', $aOptions);
-        $aElement=[];
-        $aElement['class']='badge'
-            . $this->_addClassValue($aOptions['class'],   '')
-            . $this->_addClassValue($aOptions['type'],    'badge-')
+    public function getBadge(array $aOptions): string
+    {
+        $aOptions = $this->_ensureOptions('badge', $aOptions);
+        $aElement = [];
+        $aElement['class'] = 'badge'
+            . $this->_addClassValue($aOptions['class'], '')
+            . $this->_addClassValue($aOptions['type'], 'badge-')
             . $this->_addClassValue($aOptions['bgcolor'], 'bg-')
-            ;
-        if ($aOptions['id']){
-            $aElement['id']=$aOptions['id'];
+        ;
+        if ($aOptions['id']) {
+            $aElement['id'] = $aOptions['id'];
         }
-        $aElement['title']=$aOptions['title'];
-        $aElement['label']=$aOptions['text'];
+        $aElement['title'] = $aOptions['title'];
+        $aElement['label'] = $aOptions['text'];
 
         return $this->_tag('span', $aElement);
     }
@@ -978,7 +1077,7 @@ class renderadminlte {
      * https://adminlte.io/themes/v3/pages/UI/buttons.html
      * 
      * <button type="button" class="btn btn-block btn-default">Default</button>
-     * @param type $aOptions  hash with keys for all options
+     * @param array $aOptions  hash with keys for all options
      *                          - type  - one of [none]|danger|dark|info|primary|secondary|success|warning
      *                          - size  - one of [none]|lg|sm|xs|flat
      *                          - class - any css class for customizing, eg. "disabled"
@@ -986,16 +1085,17 @@ class renderadminlte {
      *                          - text  - text on button
      * @return string
      */
-    public function getButton($aOptions){
-        $aOptions=$this->_ensureOptions('button', $aOptions);
-        $aElement=$aOptions;
-        $aElement['class']='btn'
-            . $this->_addClassValue($aOptions['type'],    'btn-')
-            . $this->_addClassValue($aOptions['size'],    'btn-')
-            . $this->_addClassValue($aOptions['class'],   '')
-            ;
-        $aElement['label']=$aOptions['text'] ? $aOptions['text'] : '&nbsp;';
-        foreach(['_infos', 'type', 'size', 'icon', 'text'] as $sDeleteKey){
+    public function getButton(array $aOptions): string
+    {
+        $aOptions = $this->_ensureOptions('button', $aOptions);
+        $aElement = $aOptions;
+        $aElement['class'] = 'btn'
+            . $this->_addClassValue($aOptions['type'], 'btn-')
+            . $this->_addClassValue($aOptions['size'], 'btn-')
+            . $this->_addClassValue($aOptions['class'], '')
+        ;
+        $aElement['label'] = $aOptions['text'] ? $aOptions['text'] : '&nbsp;';
+        foreach (['_infos', 'type', 'size', 'icon', 'text'] as $sDeleteKey) {
             unset($aElement[$sDeleteKey]);
         }
         return $this->_tag('button', $aElement);
@@ -1005,7 +1105,7 @@ class renderadminlte {
      * get a callout (box with coloered left border; has type, title + text)
      * https://adminlte.io/themes/v3/pages/UI/general.html
      * 
-     * @param type $aOptions  hash with keys for all options
+     * @param array $aOptions  hash with keys for all options
      *                        >> styling
      *                          - type    - one of [none]|danger|dark|info|primary|secondary|success|warning
      *                          - class   - optional css class
@@ -1015,19 +1115,21 @@ class renderadminlte {
      *                          - text    - text: content of the card
      * @return string
      */
-    public function getCallout($aOptions){
-        $aOptions=$this->_ensureOptions('callout', $aOptions);
-        $sClass='callout'
-            . $this->_addClassValue($aOptions['type'],    'callout-')
-            . $this->_addClassValue($aOptions['class'],   '')
-            .($aOptions['shadow'] && isset($this->_aValueMappings['shadow'][$aOptions['shadow']]) 
-                ? ' '.$this->_aValueMappings['shadow'][$aOptions['shadow']] : '')
-            ;
+    public function getCallout(array $aOptions): string
+    {
+        $aOptions = $this->_ensureOptions('callout', $aOptions);
+        $sClass = 'callout'
+            . $this->_addClassValue($aOptions['type'], 'callout-')
+            . $this->_addClassValue($aOptions['class'], '')
+            . ($aOptions['shadow'] && isset($this->_aValueMappings['shadow'][$aOptions['shadow']])
+                ? ' ' . $this->_aValueMappings['shadow'][$aOptions['shadow']] : '')
+        ;
 
         return $this->addWrapper(
-            'div', ['class'=>$sClass],
-            ($aOptions['title'] ? $this->_tag('h5', ['label'=>$aOptions['title']]) : '')
-            .($aOptions['text'] ? $this->_tag('p', ['label'=>$aOptions['text']]) : '')
+            'div',
+            ['class' => $sClass],
+            ($aOptions['title'] ? $this->_tag('h5', ['label' => $aOptions['title']]) : '')
+            . ($aOptions['text'] ? $this->_tag('p', ['label' => $aOptions['text']]) : '')
         );
     }
 
@@ -1036,7 +1138,7 @@ class renderadminlte {
      * https://adminlte.io/docs/3.2/components/cards.html
      * https://adminlte.io/docs/3.2/javascript/card-widget.html
      * 
-     * @param type $aOptions  hash with keys for all options
+     * @param array $aOptions  hash with keys for all options
      *                        >> styling
      *                          - variant: "default"  - titlebar is colored
      *                                     "outline"  - a small stripe on top border is colored
@@ -1061,67 +1163,70 @@ class renderadminlte {
      *                          - footer  - text: footer of the card
      * @return string
      */
-    public function getCard($aOptions){
-        $aOptions=$this->_ensureOptions('card', $aOptions);
+    public function getCard(array $aOptions): string
+    {
+        $aOptions = $this->_ensureOptions('card', $aOptions);
         // css class prefixes based on "variant" value
-        $aVariants=[
-            'default'  => 'card-',
-            'outline'  => 'card-outline card-',
-            'solid'    => 'bg-',
+        $aVariants = [
+            'default' => 'card-',
+            'outline' => 'card-outline card-',
+            'solid' => 'bg-',
             'gradient' => 'bg-gradient-',
         ];
 
         // window states: css class and toolbar buttons to add
-        $aStates=[
-            'collapsed'=>[ 'class'=>'collapsed-card', 'tool'=>'tb-expand'],
-            'maximized'=>[ 'class'=>'maximized-card', 'tool'=>'tb-minimize'],
+        $aStates = [
+            'collapsed' => ['class' => 'collapsed-card', 'tool' => 'tb-expand'],
+            'maximized' => ['class' => 'maximized-card', 'tool' => 'tb-minimize'],
         ];
-        $aTools=[
-            'tb-collapse'=>'<button type="button" class="btn btn-tool" data-card-widget="collapse"><i class="fa-solid fa-minus"></i></button>',
-            'tb-expand'=>'<button type="button" class="btn btn-tool" data-card-widget="collapse"><i class="fa-solid fa-plus"></i></button>',
+        $aTools = [
+            'tb-collapse' => '<button type="button" class="btn btn-tool" data-card-widget="collapse"><i class="fa-solid fa-minus"></i></button>',
+            'tb-expand' => '<button type="button" class="btn btn-tool" data-card-widget="collapse"><i class="fa-solid fa-plus"></i></button>',
 
-            'tb-maximize'=>'<button type="button" class="btn btn-tool" data-card-widget="maximize"><i class="fa-solid fa-expand"></i></button>',
-            'tb-minimize'=>'<button type="button" class="btn btn-tool" data-card-widget="maximize"><i class="fa-solid fa-compress"></i></button>',
+            'tb-maximize' => '<button type="button" class="btn btn-tool" data-card-widget="maximize"><i class="fa-solid fa-expand"></i></button>',
+            'tb-minimize' => '<button type="button" class="btn btn-tool" data-card-widget="maximize"><i class="fa-solid fa-compress"></i></button>',
 
-            'tb-remove'=>'<button type="button" class="btn btn-tool" data-card-widget="remove"><i class="fa-solid fa-times"></i></button>',
+            'tb-remove' => '<button type="button" class="btn btn-tool" data-card-widget="remove"><i class="fa-solid fa-times"></i></button>',
         ];
 
         // print_r($aOptions);
 
-        $sVariantPrefix=isset($aVariants[$aOptions['variant']]) ? $aVariants[$aOptions['variant']] : $aVariants['default'];
-        $sClass='card'
-                . $this->_addClassValue($aOptions['type'],    $sVariantPrefix)
-                .($aOptions['shadow'] && isset($this->_aValueMappings['shadow'][$aOptions['shadow']]) 
-                    ? ' '.$this->_aValueMappings['shadow'][$aOptions['shadow']] : '')
-                . $this->_addClassValue($aOptions['class'],   '')
-                ;
+        $sVariantPrefix = isset($aVariants[$aOptions['variant']]) ? $aVariants[$aOptions['variant']] : $aVariants['default'];
+        $sClass = 'card'
+            . $this->_addClassValue($aOptions['type'], $sVariantPrefix)
+            . ($aOptions['shadow'] && isset($this->_aValueMappings['shadow'][$aOptions['shadow']])
+                ? ' ' . $this->_aValueMappings['shadow'][$aOptions['shadow']] : '')
+            . $this->_addClassValue($aOptions['class'], '')
+        ;
 
         // check window state
-        foreach($aStates as $sStatus=>$aStatus){
-            if($aOptions['state']===$sStatus){
-                $sClass.=' '.$aStatus['class'];
-                $aOptions[$aStatus['tool']]=1;
+        foreach ($aStates as $sStatus => $aStatus) {
+            if ($aOptions['state'] === $sStatus) {
+                $sClass .= ' ' . $aStatus['class'];
+                $aOptions[$aStatus['tool']] = 1;
             }
         }
 
         // add toolbar buttons - from given options or by window state
-        foreach($aTools as $sTool=>$sHtml){
-            $aOptions['tools'].=($aOptions[$sTool] ? $sHtml : '');
+        foreach ($aTools as $sTool => $sHtml) {
+            $aOptions['tools'] .= ($aOptions[$sTool] ? $sHtml : '');
         }
         // build parts of the card
-        $sCardHeader=$aOptions['title'] 
-            ? $this->addWrapper('div', ['class'=>'card-header'],
-            $this->_tag('h3', ['class'=>'card-title', 'label'=>$aOptions['title']])
-            . ($aOptions['tools'] ? $this->_tag('div', ['class'=>'card-tools', 'label'=>$aOptions['tools']]) : '')
+        $sCardHeader = $aOptions['title']
+            ? $this->addWrapper(
+                'div',
+                ['class' => 'card-header'],
+                $this->_tag('h3', ['class' => 'card-title', 'label' => $aOptions['title']])
+                . ($aOptions['tools'] ? $this->_tag('div', ['class' => 'card-tools', 'label' => $aOptions['tools']]) : '')
             )
             : ''
-            ;
+        ;
 
-        $sCardBody=$this->_tag('div', ['class'=>'card-body', 'label'=>$aOptions['text']]);
-        $sCardFooter=$aOptions['footer'] ? $this->_tag('div', ['class'=>'card-footer', 'label'=>$aOptions['footer']]) : '';
+        $sCardBody = $this->_tag('div', ['class' => 'card-body', 'label' => $aOptions['text']]);
+        $sCardFooter = $aOptions['footer'] ? $this->_tag('div', ['class' => 'card-footer', 'label' => $aOptions['footer']]) : '';
 
         // merge all
-        return $this->addWrapper('div', ['class'=>$sClass], $sCardHeader.$sCardBody.$sCardFooter);
+        return $this->addWrapper('div', ['class' => $sClass], $sCardHeader . $sCardBody . $sCardFooter);
     }
 
 
@@ -1144,39 +1249,44 @@ class renderadminlte {
      *                          - progresstext  - text below progress bar
      * @return string
      */
-    public function getInfobox($aOptions){
-        $aOptions=$this->_ensureOptions('infobox', $aOptions);
+    public function getInfobox(array $aOptions): string
+    {
+        $aOptions = $this->_ensureOptions('infobox', $aOptions);
 
         // print_r($aOptions);
-        $sClass='info-box'
-                . $this->_addClassValue($aOptions['type'],    'bg-')
-                . $this->_addClassValue($aOptions['class'],   '')
-                .($aOptions['shadow'] && isset($this->_aValueMappings['shadow'][$aOptions['shadow']]) 
-                    ? ' '.$this->_aValueMappings['shadow'][$aOptions['shadow']] : '')
-                ;
-        
+        $sClass = 'info-box'
+            . $this->_addClassValue($aOptions['type'], 'bg-')
+            . $this->_addClassValue($aOptions['class'], '')
+            . ($aOptions['shadow'] && isset($this->_aValueMappings['shadow'][$aOptions['shadow']])
+                ? ' ' . $this->_aValueMappings['shadow'][$aOptions['shadow']] : '')
+        ;
+
         // build parts
-        $sIcon=$aOptions['icon'] 
+        $sIcon = $aOptions['icon']
             ? $this->addWrapper("span", [
-                    'class'=>'info-box-icon'.($aOptions['iconbg'] ? ' bg-'.$aOptions['iconbg'] : '')
-                ], $this->_tag('i',['class'=>$aOptions['icon']])) 
+                'class' => 'info-box-icon' . ($aOptions['iconbg'] ? ' bg-' . $aOptions['iconbg'] : '')
+            ], $this->_tag('i', ['class' => $aOptions['icon']]))
             : ''
-            ;
-        $sContent=$this->addWrapper("div", ['class'=>'info-box-content'],
+        ;
+        $sContent = $this->addWrapper(
+            "div",
+            ['class' => 'info-box-content'],
             ''
-            . ($aOptions['text']   ? $this->_tag('span', ['class'=>'info-box-text',   'label'=>$aOptions['text']])   : '')
-            . ($aOptions['number'] ? $this->_tag('span', ['class'=>'info-box-number', 'label'=>$aOptions['number']]) : '')
-            . ($aOptions['progressvalue']!==false && $aOptions['progressvalue']!=='' 
-                ? $this->addWrapper('div', ['class'=>'progress'],
-                        $this->_tag('div', ['class'=>'progress-bar'. ($aOptions['iconbg'] ? ' bg-'.$aOptions['iconbg'] : ''), 'style'=>'width: '.(int)$aOptions['progressvalue'].'%' ]) 
-                    )
-                    . ($aOptions['progresstext'] ? $this->_tag('span', ['class'=>'progress-description', 'label'=>$aOptions['progresstext']]) : '' )
-                : ''    
-                ) 
+            . ($aOptions['text'] ? $this->_tag('span', ['class' => 'info-box-text', 'label' => $aOptions['text']]) : '')
+            . ($aOptions['number'] ? $this->_tag('span', ['class' => 'info-box-number', 'label' => $aOptions['number']]) : '')
+            . ($aOptions['progressvalue'] !== false && $aOptions['progressvalue'] !== ''
+                ? $this->addWrapper(
+                    'div',
+                    ['class' => 'progress'],
+                    $this->_tag('div', ['class' => 'progress-bar' . ($aOptions['iconbg'] ? ' bg-' . $aOptions['iconbg'] : ''), 'style' => 'width: ' . (int) $aOptions['progressvalue'] . '%'])
+                )
+                . ($aOptions['progresstext'] ? $this->_tag('span', ['class' => 'progress-description', 'label' => $aOptions['progresstext']]) : '')
+                : ''
+            )
         );
 
         // merge all
-        return $this->_tag('div', ['class'=>$sClass], $sIcon.$sContent);
+        return $this->_tag('div', ['class' => $sClass], $sIcon . $sContent);
     }
 
 
@@ -1186,7 +1296,7 @@ class renderadminlte {
      * https://adminlte.io/docs/3.2/components/boxes.html
      * https://adminlte.io/themes/v3/pages/widgets.html
      * 
-     * @param type $aOptions  hash with keys for all options
+     * @param array $aOptions  hash with keys for all options
      *                        styling:
      *                          - type    - color of the box; one of [none]|danger|dark|info|primary|secondary|success|warning
      *                          - shadow  - size of shadow; one of [none] (=default: between small and regular)|none|small|regular|large 
@@ -1198,42 +1308,50 @@ class renderadminlte {
      *                          - linktext- text below progress bar
      * @return string
      */
-    public function getSmallbox($aOptions){
-        $aOptions=$this->_ensureOptions('smallbox', $aOptions);
+    public function getSmallbox(array $aOptions): string
+    {
+        $aOptions = $this->_ensureOptions('smallbox', $aOptions);
         // print_r($aOptions);
-        $sClass='small-box'
-                . $this->_addClassValue($aOptions['type'],    'bg-')
-                . $this->_addClassValue($aOptions['class'],   '')
-                .($aOptions['shadow'] && isset($this->_aValueMappings['shadow'][$aOptions['shadow']]) 
-                    ? ' '.$this->_aValueMappings['shadow'][$aOptions['shadow']] : '')
-                ;
-        
+        $sClass = 'small-box'
+            . $this->_addClassValue($aOptions['type'], 'bg-')
+            . $this->_addClassValue($aOptions['class'], '')
+            . ($aOptions['shadow'] && isset($this->_aValueMappings['shadow'][$aOptions['shadow']])
+                ? ' ' . $this->_aValueMappings['shadow'][$aOptions['shadow']] : '')
+        ;
+
         // build parts
-        $sContent=$this->addWrapper("div", ['class'=>'inner'],
+        $sContent = $this->addWrapper(
+            "div",
+            ['class' => 'inner'],
             ''
-            . ($aOptions['number'] ? $this->_tag('h3', ['label'=>$aOptions['number']]) : '')
-            . ($aOptions['text']   ? $this->_tag('p', ['class'=>'info-box-text',   'label'=>$aOptions['text']])   : '')
+            . ($aOptions['number'] ? $this->_tag('h3', ['label' => $aOptions['number']]) : '')
+            . ($aOptions['text'] ? $this->_tag('p', ['class' => 'info-box-text', 'label' => $aOptions['text']]) : '')
         );
-        $sIcon=$aOptions['icon'] 
-            ? $this->addWrapper("div", ['class'=>'icon'], 
-                $this->_tag('i',['class'=>$aOptions['icon']])) 
+        $sIcon = $aOptions['icon']
+            ? $this->addWrapper(
+                "div",
+                ['class' => 'icon'],
+                $this->_tag('i', ['class' => $aOptions['icon']])
+            )
             : ''
-            ;
-        $sFooter=($aOptions['url']
-            ? $this->addWrapper("a", [
-                'class'=>'small-box-footer',
-                'href'=>$aOptions['url'],
+        ;
+        $sFooter = ($aOptions['url']
+            ? $this->addWrapper(
+                "a",
+                [
+                    'class' => 'small-box-footer',
+                    'href' => $aOptions['url'],
                 ],
                 ''
                 . ($aOptions['linktext'] ? $aOptions['linktext'] : $aOptions['url'])
                 . ' '
-                . $this->_tag('i',['class'=>'fa-solid fa-arrow-circle-right'])
+                . $this->_tag('i', ['class' => 'fa-solid fa-arrow-circle-right'])
             )
             : ''
         );
 
         // merge all
-        return $this->_tag('div', ['class'=>$sClass], $sContent.$sIcon.$sFooter);
+        return $this->_tag('div', ['class' => $sClass], $sContent . $sIcon . $sFooter);
     }
 
     // ----------------------------------------------------------------------
@@ -1243,12 +1361,27 @@ class renderadminlte {
     // ----------------------------------------------------------------------
 
 
-    public function getHorizontalFormElement($sInput, $sLabel=false, $sId=false){
+    /**
+     * Generates a horizontal form element with a label, input, and optional hint.
+     *
+     * @param string $sInput The HTML input element to be rendered.
+     * @param string $sLabel The label for the input element.
+     * @param string $sId The ID attribute for the label and input elements.
+     * @param string $sHint An optional hint to be displayed below the input element.
+     * @return string The generated HTML for the horizontal form element.
+     */
+    public function getHorizontalFormElement(string $sInput, string $sLabel = '', string $sId = '', string $sHint=''): string
+    {
         return '<div class="form-group row">'
-                . '<label for="' . $sId . '" class="col-sm-2 col-form-label">' . $sLabel . '</label>'
-                . '<div class="col-sm-10">'.$sInput.'</div>'
-              . '</div>'
-              ;
+            . '<label for="' . $sId . '" class="col-sm-2 col-form-label">' . $sLabel . '</label>'
+            . '<div class="col-sm-10">'
+            . ($sHint 
+                ? '<div class="text-navy hint">' . $sHint . '</div>' 
+                : '')
+            . $sInput
+            . '</div>'
+            . '</div>'
+        ;
     }
 
     /**
@@ -1258,67 +1391,83 @@ class renderadminlte {
      * @param array $aOptions  hash with keys for all options
      *                        styling:
      *                          - type    - field type: text, email, password, hidden and all other html 5 input types
-      *                        content
+     *                        content
      *                          - label   - label tag
      *                          - name    - name attribute for sending form
      *                          - value   - value in field
+     *                        more:
+     *                          - hint    - hint to be displayed above the field
+     *                                      If not set, no hint is displayed.
+     *                                      css for ".row .hint" to customize look and feel
      * @return string
      */
-    public function GetFormInput($aOptions){
+    public function GetFormInput(array $aOptions): string
+    {
         // $aOptions=$this->_ensureOptions('input', $aOptions);
-        $aElement=$aOptions;
-        $aElement['class']=''
+        $aElement = $aOptions;
+        $aElement['class'] = ''
             . 'form-control '
-            . (isset($aOptions['class']) ? $aOptions['class']: '')
-            ;
-        $sFormid=(isset($aOptions['id']) 
-            ? $aOptions['id'] 
-            : (isset($aOptions['name']) ? $aOptions['name'] : 'field' ).'-'.md5(microtime(true))
+            . (isset($aOptions['class']) ? $aOptions['class'] : '')
+        ;
+        $sFormid = (isset($aOptions['id'])
+            ? $aOptions['id']
+            : (isset($aOptions['name']) ? $aOptions['name'] : 'field') . '-' . md5(microtime(true))
         );
+        $aElement['id'] = $sFormid;
 
-        $sLabel=isset($aOptions['label']) ? $aOptions['label'] : '';
-        $sPrepend='';
-        $sAppend='';
+        $sLabel = isset($aOptions['label']) ? $aOptions['label'] : '';
+        $sHint = isset($aOptions['hint']) ? $aOptions['hint'] : '';
+        $sPrepend = '';
+        $sAppend = '';
 
 
-        if(isset($aOptions['prepend']) && $aOptions['prepend']){
-            $sWrapperclass='input-group';
-            $sPrepend=$this->_tag('div',[ 'class'=>'input-group-prepend'],
-                $this->_tag('span', ['class'=>'input-group-text'] , $aOptions['prepend'])
+        if (isset($aOptions['prepend']) && $aOptions['prepend']) {
+            $sWrapperclass = 'input-group';
+            $sPrepend = $this->_tag(
+                'div',
+                ['class' => 'input-group-prepend'],
+                $this->_tag('span', ['class' => 'input-group-text'], $aOptions['prepend'])
             );
         }
-        if(isset($aOptions['append']) && $aOptions['append']){
-            $sWrapperclass='input-group';
-            $sAppend=$this->_tag('div',[ 'class'=>'input-group-append'],
-                $this->_tag('span', ['class'=>'input-group-text'] , $aOptions['append'])
+        if (isset($aOptions['append']) && $aOptions['append']) {
+            $sWrapperclass = 'input-group';
+            $sAppend = $this->_tag(
+                'div',
+                ['class' => 'input-group-append'],
+                $this->_tag('span', ['class' => 'input-group-text'], $aOptions['append'])
             );
-        }  
+        }
 
-        $aElement['id']=$sFormid;
-        foreach(['_infos', 'label', 'append', 'prepend', 'debug'] as $sDeleteKey){
-            if(isset($aElement[$sDeleteKey])){
+        foreach (['_infos', 'label', 'append', 'prepend', 'debug'] as $sDeleteKey) {
+            if (isset($aElement[$sDeleteKey])) {
                 unset($aElement[$sDeleteKey]);
             }
         }
 
         // return data
 
-        switch($aElement['type']){
+        switch ($aElement['type']) {
             case 'checkbox':
             case 'radio':
-                $aElement['class']=str_replace('form-control ', 'form-check-input', $aElement['class']);
-                return $this->_tag('div' , ['class'=>'form-check'],
-                    $this->_tag('input', $aElement, '', false).$this->_tag('label', ['for'=>$sFormid, 'label'=>$sLabel ], '')
+                $aElement['class'] = str_replace('form-control ', 'form-check-input', $aElement['class']);
+                $aElement['title'] = $aElement['title'] ?? $sHint;
+                return $this->_tag(
+                    'div',
+                    ['class' => 'form-check'],
+                    $this->_tag('input', $aElement, '', false) . $this->_tag('label', ['for' => $sFormid, 'label' => $sLabel], '')
                 );
                 break;
             case 'hidden':
+                $aElement['title'] = $aElement['title'] ?? $sHint;
                 return $this->_tag('input', $aElement, '', false);
                 break;
-            default: return $this->getHorizontalFormElement(
-                $sPrepend.$this->_tag('input', $aElement, '', false).$sAppend, 
-                $sLabel, 
-                $sFormid
-            );
+            default:
+                return $this->getHorizontalFormElement(
+                    $sPrepend . $this->_tag('input', $aElement, '', false) . $sAppend,
+                    $sLabel,
+                    $sFormid,
+                    $sHint
+                );
         }
     }
 
@@ -1331,32 +1480,41 @@ class renderadminlte {
      *                          - label   - label tag
      *                          - name    - name attribute for sending form
      *                          - value   - value in 
+     *                        more:
+     *                          - hint    - hint to be displayed above the field
+     *                                      If not set, no hint is displayed.
+     *                                      css for ".row .hint" to customize look and feel
      * @return string
      */
-    public function getFormTextarea($aOptions){
+    public function getFormTextarea(array $aOptions): string
+    {
         // $aOptions=$this->_ensureOptions('textarea', $aOptions);
-        $aElement=$aOptions;
-        $aElement['class']=''
+        $aElement = $aOptions;
+        $aElement['class'] = ''
             . 'form-control '
-            . ((isset($aOptions['type']) && $aOptions['type']=='html' )? 'summernote ': '')
-            . (isset($aOptions['class']) ? $aOptions['class']: '')
+            . ((isset($aOptions['type']) && $aOptions['type'] == 'html') ? 'summernote ' : '')
+            . (isset($aOptions['class']) ? $aOptions['class'] : '')
         ;
-        
-        $sLabel=isset($aOptions['label']) ? $aOptions['label'] : '';
-        $sFormid=(isset($aOptions['id']) 
-            ? $aOptions['id'] 
-            : (isset($aOptions['name']) ? $aOptions['name'] : 'field' ).'-'.md5(microtime(true))
+        $sFormid = (isset($aOptions['id'])
+            ? $aOptions['id']
+            : (isset($aOptions['name']) ? $aOptions['name'] : 'field') . '-' . md5(microtime(true))
         );
-        $value=isset($aOptions['value']) ? $aOptions['value']: '';
-        foreach(['_infos', 'label', 'debug','type', 'value'] as $sDeleteKey){
-            if(isset($aElement[$sDeleteKey])){
+        $sLabel = isset($aOptions['label']) ? $aOptions['label'] : '';
+        $sHint = isset($aOptions['hint']) ? $aOptions['hint'] : '';
+        $aElement['id'] = $sFormid;
+
+        $value = isset($aOptions['value']) ? $aOptions['value'] : '';
+
+        foreach (['_infos', 'label', 'debug', 'type', 'value'] as $sDeleteKey) {
+            if (isset($aElement[$sDeleteKey])) {
                 unset($aElement[$sDeleteKey]);
             }
         }
         return $this->getHorizontalFormElement(
-            $this->_tag('textarea', $aElement, $value), 
-            $sLabel, 
-            $sFormid
+            $this->_tag('textarea', $aElement, $value),
+            $sLabel,
+            $sFormid,
+            $sHint
         );
 
     }
@@ -1364,52 +1522,69 @@ class renderadminlte {
     /**
      * return a select box field
      * @param array $aOptions  hash with keys for all options
-     *                        styling:
-     *                          - class   - css class
      *                        option fields
      *                          - options - array of options with keys per item:
      *                              - value   - value in the option
      *                              - label   - visible text in the option
      *                              other keys are attributes in the option
+     *                        styling:
+     *                          - bootstrap-select  - set true to enable select
+     *                                      box with bootstrap-select and
+     *                                      live search
+     *                          - class   - css class
      *                        select tag
      *                          - label   - label tag
      *                          - name    - name attribute for sending form
      *                          other keys are attributes in the select
+     *                        more:
+     *                          - hint    - hint to be displayed above the field
+     *                                      If not set, no hint is displayed.
+     *                                      css for ".row .hint" to customize look and feel
      * @return string
      */
-    public function getFormSelect($aOptions){
-        $aElement=$aOptions;
-        $aElement['class']=''
+    public function getFormSelect(array $aOptions): string
+    {
+        $aElement = $aOptions;
+        $aElement['class'] = ''
             . 'form-control '
-            . (isset($aOptions['class']) ? $aOptions['class']: '')
+            . (isset($aOptions['class']) ? $aOptions['class'] . ' ' : '')
+            . (isset($aOptions['bootstrap-select']) ? 'selectpicker ' : '') //$aOptions
         ;
-        
-        $sLabel=isset($aOptions['label']) ? $aOptions['label'] : '';
-        $sFormid=(isset($aOptions['id']) 
-        
-            ? $aOptions['id'] 
-            : (isset($aOptions['name']) ? $aOptions['name'] : 'field' ).'-'.md5(microtime(true))
+        if (isset($aOptions['bootstrap-select']) && $aOptions['bootstrap-select']) {
+            $aElement['data-live-search'] = "true";
+        }
+
+        $sFormid = (isset($aOptions['id'])
+
+            ? $aOptions['id']
+            : (isset($aOptions['name']) ? $aOptions['name'] : 'field') . '-' . md5(microtime(true))
         );
+        $aElement['id'] = $sFormid;
+        $sLabel = isset($aOptions['label']) ? $aOptions['label'] : '';
+        $sHint = isset($aOptions['hint']) ? $aOptions['hint'] : '';
 
-        $sOptionTags='';
-        foreach($aOptions['options'] as $aField){
-            $optionText=$aField['label'];
+        $sOptionTags = '';
+        foreach ($aOptions['options'] as $aField) {
+            $optionText = $aField['label'];
             unset($aField['label']);
-            $sOptionTags.=$this->_tag('option', $aField, $optionText )."\n";
+            $sOptionTags .= $this->_tag('option', $aField, $optionText) . "\n";
         }
 
-        foreach(['_infos', 'label', 'debug','type', 'value', 'options'] as $sDeleteKey){
-            if(isset($aElement[$sDeleteKey])){
+        foreach (['_infos', 'label', 'debug', 'type', 'value', 'options'] as $sDeleteKey) {
+            if (isset($aElement[$sDeleteKey])) {
                 unset($aElement[$sDeleteKey]);
             }
         }
         return $this->getHorizontalFormElement(
-            $this->_tag('div', ['class'=>'form-group'],
+            $this->_tag(
+                'div',
+                ['class' => 'form-group'],
                 $this->_tag('select', $aElement, $sOptionTags)
-                ), 
-                $sLabel, 
-                $sFormid
-            );
+            ),
+            $sLabel,
+            $sFormid,
+            $sHint
+        );
 
     }
 
@@ -1423,55 +1598,62 @@ class renderadminlte {
      * return a box with tabbed content
      * @param array $aOptions  hash with keys for all options
      *                           - tabs {array} key=tab label; value=content
-     * @retunr string|array
+     * @param bool  $asArray   optional flag: return hash with keys or as string
+     * @retunr bool|string|array
      */
-    public function getTabbedContent($aOptions, $asArray=false){
+    public function getTabbedContent(array $aOptions, bool $asArray = false): bool|string|array
+    {
         static $iTabCounter;
-        if( ! isset($aOptions['tabs']) || ! is_array($aOptions['tabs']) ){
+        if (!isset($aOptions['tabs']) || !is_array($aOptions['tabs'])) {
             return false;
         }
-        if (!isset($iTabCounter)){
-            $iTabCounter=1;
+        if (!isset($iTabCounter)) {
+            $iTabCounter = 1;
         } else {
-            $iTabCounter++;            
+            $iTabCounter++;
         }
 
-        $id='tab-content-'.$iTabCounter;
-        $iCounter=0;
+        $id = 'tab-content-' . $iTabCounter;
+        $iCounter = 0;
 
-        $sTabs='';
-        $sContent='';
-        foreach($aOptions['tabs'] as $sLabel => $sTabContent){
+        $sTabs = '';
+        $sContent = '';
+        foreach ($aOptions['tabs'] as $sLabel => $sTabContent) {
             $iCounter++;
-            $sTabId=$id.'-tabitem-'.$iCounter.'-tab';
-            $sContentId=$id.'-tabitem-'.$iCounter.'-content';
-
-            $sTabs.=$this->_tag('li', ['class'=>'nav-item'], 
-                $this->_tag('a', [
-                    'class'=>'nav-link'.($iCounter==1 ? ' active' : '' ),
-                    'id'=>$sTabId,
-                    'data-toggle'=>'tab',
-                    'href'=>'#'.$sContentId,
-                    'role'=>'tab',
-                    'aria-controls'=>'custom-tabs-one-profile',
-                    'aria-selected'=>($iCounter==1 ? true : false ), 
-                    ], 
-                    $sLabel)
+            $sTabId = $id . '-tabitem-' . $iCounter . '-tab';
+            $sContentId = $id . '-tabitem-' . $iCounter . '-content';
+
+            $sTabs .= $this->_tag(
+                'li',
+                ['class' => 'nav-item'],
+                $this->_tag(
+                    'a',
+                    [
+                        'class' => 'nav-link' . ($iCounter == 1 ? ' active' : ''),
+                        'id' => $sTabId,
+                        'data-toggle' => 'tab',
+                        'href' => '#' . $sContentId,
+                        'role' => 'tab',
+                        'aria-controls' => 'custom-tabs-one-profile',
+                        'aria-selected' => ($iCounter == 1 ? true : false),
+                    ],
+                    $sLabel
+                )
             );
-            $sContent.=$this->_tag('div', [
-                'class'=>'tab-pane fade'.($iCounter==1 ? ' active show' : ''), 
-                'id'=>$sContentId,
-                'role'=>'tabpanel',
-                'aria-labelledby'=>$sTabId,
-                ], $sTabContent);
+            $sContent .= $this->_tag('div', [
+                'class' => 'tab-pane fade' . ($iCounter == 1 ? ' active show' : ''),
+                'id' => $sContentId,
+                'role' => 'tabpanel',
+                'aria-labelledby' => $sTabId,
+            ], $sTabContent);
         }
-        $sTabs=$this->_tag('ul', ['class'=>'nav nav-tabs', 'role'=>'tablist'], $sTabs);
-        $sContent=$this->_tag('div', ['class'=>'tab-content'], $sContent);
+        $sTabs = $this->_tag('ul', ['class' => 'nav nav-tabs', 'role' => 'tablist'], $sTabs);
+        $sContent = $this->_tag('div', ['class' => 'tab-content'], $sContent);
 
         return $asArray
-            ? ['tabs'=>$sTabs, 'content'=>$sContent]
+            ? ['tabs' => $sTabs, 'content' => $sContent]
             : $sTabs . $sContent
-            ;
+        ;
     }
 
 }