00005 Category Header and Background Modification

Below is a recipe to turn your nested lists into “flat” bordered panels, each level with its own background color + opacity, and a left-to-right layout of:

  1. Count badge
  2. Collapse toggle
  3. Category image
  4. Title + description
  5. …three-dot admin menu

1) Add per-category styling fields

In your AbcdirectoryCategory ActiveRecord, make sure you have two new columns (and form fields) in your Category table:

  • bg_color (string, e.g. #FF0000)
  • bg_opacity (decimal between 0 and 1)

These let each category define its own background and translucency.


2) Expose defaults in module configuration

In Configuration.php add two new settings (with defaults) so admins can override:

// protected/modules/abcdirectory/models/Configuration.php

/** @var string Default header bg-color if category has none */ 
public $defaultCategoryColor = '#ffffff';
/** @var float Default opacity if category has none */ 
public $defaultCategoryOpacity = 0.2;

public function rules(): array
{
    return array_merge(parent::rules(), [
        [['defaultCategoryOpacity'], 'number', 'min' => 0, 'max' => 1],
        [['defaultCategoryColor'], 'string', 'match' => '/^#[0-9A-Fa-f]{6}$/'],
    ]);
}

public function attributeLabels(): array
{
    return array_merge(parent::attributeLabels(), [
        'defaultCategoryColor'   => Yii::t('AbcdirectoryModule.config', 'Default Category Color'),
        'defaultCategoryOpacity' => Yii::t('AbcdirectoryModule.config', 'Default Category Opacity'),
    ]);
}

Then add the corresponding form fields in views/config/index.php under your “Classified spaces browser” section:

<?= $form->field($model, 'defaultCategoryColor')->input('color') ?>
<?= $form->field($model, 'defaultCategoryOpacity')->input('number', [
        'step' => 0.05, 'min' => 0, 'max' => 1,
    ])->hint(Yii::t('AbcdirectoryModule.config', 'Opacity from 0 (transparent) to 1 (opaque)')) ?>

3) Render each item with inline rgba background

Update widgets/SpaceBrowserCategoryItem.php to pass both values into the view:

<?php
namespace humhub\modules\abcdirectory\widgets;

use humhub\components\Widget;
use Yii;
use humhub\libs\Html;
use humhub\modules\abcdirectory\helpers\ColorHelper;

class SpaceBrowserCategoryItem extends Widget
{
    public \humhub\modules\abcdirectory\models\AbcdirectoryCategory $category;

    public function run()
    {
        $cfg = Yii::$app->getModule('abcdirectory')->getConfiguration();

        // pick category color or fallback
        $hex     = $this->category->bg_color   ?: $cfg->defaultCategoryColor;
        $opacity = $this->category->bg_opacity ?? $cfg->defaultCategoryOpacity;

        // compute RGBA
        $bgCss = ColorHelper::hexToRgba($hex, $opacity);

        // count spaces in category + direct children
        $nbSpaces = $this->category->getAbcdirectorys()->count();
        foreach ($this->category->children as $child) {
            $nbSpaces += $child->getAbcdirectorys()->count();
        }

        return $this->render('spaceBrowserCategoryItem', [
            'category' => $this->category,
            'nbSpaces' => $nbSpaces,
            'bgCss'    => $bgCss,
        ]);
    }
}

4) The item HTML + CSS classes

Create widgets/views/spaceBrowserCategoryItem.php like this:

<?php
/**
 * @var \humhub\modules\ui\view\components\View $this
 * @var \humhub\modules\abcdirectory\models\AbcdirectoryCategory $category
 * @var int    $nbSpaces
 * @var string $bgCss    // computed "rgba(...)" from the widget
 */
use humhub\libs\Html;
use humhub\modules\abcdirectory\widgets\CategoryImage;
?>

<div class="csb-category-item d-flex align-items-start"
     style="background:<?= Html::encode($bgCss) ?>; border:1px solid #ccc; padding:.5em; margin-bottom:.75em;">
    <!-- [1] Count badge + caret -->
    <div class="csb-icon-stack flex-shrink-0" style="margin-right:.75em; text-align:center;">
        <span class="glyphicon glyphicon-chevron-down"></span><br>
        <span class="badge cs-badge-count"><?= $nbSpaces ?></span>
    </div>

    <!-- [2] Image -->
    <div class="flex-shrink-0" style="margin-right:.75em;">
        <?= CategoryImage::widget(['category' => $category, 'height' => 40]) ?>
    </div>

    <!-- [3] Title & description -->
    <div class="flex-grow-1">
        <h5 class="mb-1"><?= Html::encode($category->name) ?></h5>
        <?php if ($category->description): ?>
            <p class="text-muted mb-0">
                <?= Html::encode(\yii\helpers\BaseStringHelper::truncate($category->description, 100)) ?>
            </p>
        <?php endif; ?>
    </div>

    <!-- [4] three-dot admin menu (if any) -->
    <div class="flex-shrink-0 csb-admin-menu">
        <?= \humhub\modules\abcdirectory\widgets\menus\CategoryAdminMenu::widget(['category' => $category]) ?>
    </div>
</div>

Key CSS (add to your module’s LESS/CSS file so every level is the same width, no indent):

// modules/abcdirectory/resources/less/_spaceBrowser.less

.csb-category-item {
  width: 100%;               // full width
  border-radius: .25rem;
  // remove any nested padding-left
  padding-left: .5rem !important;
  // ensure collapse toggles inside don’t indent
  .panel-collapse & {
    margin-left: 0 !important;
  }
}

// override the default panel <ul><li> indentation
.csb-accordion ul {
  list-style: none;
  padding-left: 0;
  margin: 0;
}

Then rebuild your CSS:

cd protected/modules/abcdirectory/resources/less
chmod +x build.sh && ./build.sh
cd ../../../..
rm -rf protected/runtime/cache/* protected/runtime/assets/*

5) Hook the new widget into your tree

In your _categoryTree.php (or _spaceBrowserSectionParentCategory.php), replace the old heading call with:

<?= SpaceBrowserCategoryItem::widget(['category' => $category]) ?>

And remove any <ul> indentation around it. Your recursive render should simply echo one SpaceBrowserCategoryItem per category, then recurse—no extra padding.


Result

  • Flat panels (no indent) but nested 1px borders show each level
  • Per-category RGBA backgrounds defined in the DB + fallback/defaults
  • A consistent flex layout: badge+caret, image, title+desc, menu

This gives you full control over colors, opacity, and styling at every category level while keeping the width and spacing uniform.