Creating a "Featured Categories" homepage banner

I looked over this previous post by Kris and directly adapted it to something you may be able to use as a base. Much of what is covered here has been laid out by him in his original topic.

All of the code will be added to the </head> (head_tag.html) section of your theme.

This first section will check to see if the page you are on is the “home page”.

We will then get the sites categories using the Category.list() method on the category class.

We will then compare those to the categories you will want featured. These will be located in the definedFeaturedCategories array defined in the code below. The ones you allow will be set to the component to be passed along to a template for rendering.

<script type="text/discourse-plugin" version="0.8">
  const Category = require("discourse/models/category").default;
  // we will use the Category model to retrieve site categories

  api.registerConnectorClass('above-main-container', 'featured-categories', {
    // above-main-container is the plugin outlet,
    // featured-topics is your custom component name

    setupComponent(args, component) {

      api.onPageChange((url, title) => {
        console.log(url,title)
        if ((url === "/") || (url === "/latest") ) {
        // on page change, check if url matches
        // if your homepage isn't /latest change this to /categories
        
          $('html').addClass('custom-featured-categories');
          // add a class to the HTML tag for easy CSS targetting

          let definedFeaturedCategories = ["uncategorized","blog","two"]
          // array of categories you want to feature
          // be sure to put the category titles in lowercase

          let featuredCategories = [];

          categories = Category.list();

          for (let cat of categories) {
            if (definedFeaturedCategories.includes(cat.name.toLowerCase())) {
              // only pushes categories you want to feature into the array to be rendered
              featuredCategories.push(cat)
            }
          }

          component.set('featuredCategories', featuredCategories)

        } else {

        // If the page doesn't match the urls above, do this:
          $('html').removeClass('custom-featured-categories');
          // Remove our custom class
          component.set('categories',[])
          // set the categories to an empty array to disable rendering
        }
      });
    }
  });
</script>

This next section injects the template for the component created above into the plugin outlet above-main-container. It will call the custom categories-wrapper created in the third step and define categories to be featuredCategories created above.

<script type="text/x-handlebars" data-template-name="/connectors/above-main-container/featured-categories">
      <div class="custom-featured-categories-wrapper">
        {{categories-wrapper categories=featuredCategories}}
          <!-- use the categories-wrapper template created below -->
          <!-- define categories to be featuredCategories created in the script above -->
      </div>
</script>

The third section creates the custom categories-wrapper handlebars template to render the featured categories. It is directly adapted from the Discourse categories-only.hbs used on Discourse’s categories page.

<script type="text/x-handlebars" data-template-name="components/categories-wrapper">
  <!-- This creates a component template called 'categories wrapper' -->
  <!-- All of this template code was adapted from Discourse's own categories page template
   https://github.com/discourse/discourse/blob/acd1693dac1bff6ff50250d942134bc48a27ff14/app/assets/javascripts/discourse/templates/components/categories-only.hbs -->

  <div class="top-categories-wrapper">
    {{#each categories as |c|}}
        <div class="top-category-column-one">
          {{category-title-link category=c}}
          {{#if c.escription}}
            <div class="category-description">
              {{dir-span c.description}}
            </div>
          {{/if}}
          {{#if c.isGrandParent}}
            <table class="category-list subcategories-with-subcategories">
              <tbody>
                {{#each c.subcategories as |subcategory|}}
                  <tr
                    data-category-id={{subcategory.id}}
                    data-notification-level={{subcategory.notificationLevelString
                    }}
                    class="{{if
                        subcategory.description_excerpt
                        "has-description"
                        "no-description"
                      }}
  
                      {{if subcategory.uploaded_logo.url "has-logo" "no-logo"}}"
                  >
                    <td
                      class="category"
                      style={{border-color subcategory.color}}
                    >
                      {{category-title-link tagName="h4" category=subcategory}}
                      {{#if subcategory.description_excerpt}}
                        <div
                          class="category-description subcategory-description"
                        >
                          {{{dir-span subcategory.description_excerpt}}}
                        </div>
                      {{/if}}
                      {{#if subcategory.subcategories}}
                        <div class="subcategories">
                          {{#each subcategory.subcategories as |subsubcategory|
                          }}
                            {{#unless subsubcategory.isMuted}}
                              <span class="subcategory">
                                {{category-title-before category=subsubcategory
                                }}
                                {{category-link subsubcategory hideParent="true"
                                }}
                              </span>
                            {{/unless}}
                          {{/each}}
                        </div>
                      {{else if subcategory.description_excerpt}}
                        <div
                          class="category-description subcategory-description"
                        >
                          {{{dir-span subcategory.description_excerpt}}}
                        </div>
                      {{/if}}
                    </td>
                  </tr>
                {{/each}}
              </tbody>
            </table>
          {{else if c.subcategories}}
            <div class="subcategories">
              {{#each c.subcategories as |subcategory|}}
                {{#unless subcategory.isMuted}}
                  <span class="subcategory">
                    {{category-title-before category=subcategory}}
                    {{category-link subcategory hideParent="true"}}
                    {{category-unread category=subcategory}}
                  </span>
                {{/unless}}
              {{/each}}
            </div>
          {{/if}}
        </div>
        <div class="top-category-column-two">
          <span class="topics-header">
            Topics
          </span>
          <span class="topics-count">
            {{c.topic_count}}
          </span>
          {{category-unread category=c tagName="div" class="unread-new"}}
        </div>
    {{/each}}
  </div>
</script>

This should help you begin to do what you requested in your OP.

For styling the color of each category box according to its custom defined colors, in the third section, you can hard-code styles using # + c.color to access the categories color code.

Other than that, styling can be done in the common.scss file.

7 Likes