Add Support for the Imagery Feature

Just to recap – what are the reasons why we might want to implement the Image feature in our theme? First, we can add custom behaviors to Imagery block types without worrying about their default behaviors. Additionally, we can ensure outdated, unnecessary and perhaps contradictory JavaScript and CSS files we're not using are not loaded when rendering Imagery block types.

Existing Presentation

Before we do anything, let's make sure we have a good place to test our changes. Let's add a new page to our theme, and add every single block type that uses the Imagery feature to that page.

Image Slider

#

Hero Image

#

Gallery

#

And here's a picture of the active image showing, post-click, in a lightbox:

#

We haven't built any support for this functionality into our theme; it's all working because the Features system detects this, and provides the fallback assets instead. The functionality for all of this is found in the following two CSS and JavaScript assets, which are automatically included in the header and footer:

<link href="/concrete/css/features/imagery/frontend.css?ccm_nocache=c5180c4efa06f25724edfa859fe86bd591c9deed" rel="stylesheet" type="text/css" media="all">
<script type="text/javascript" src="/concrete/js/features/imagery/frontend.js?ccm_nocache=c5180c4efa06f25724edfa859fe86bd591c9deed"></script>

Remove Fallback Assets

To bundle custom feature functionality in our Flintstone theme, let's first remove the fallback assets. In order to do this, just register your theme as providing that feature. This can be done by implementing getThemeSupportedFeatures in your PageTheme class.

Remember! Since the BedrockThemeTrait automatically provides support for the basics and typography features, make sure you mark those as provided in your custom getThemeSupportedFeatures implementation!

Let's add imagery to our list of supported features, by implementing getThemeSupportedFeatures in our PageTheme class. First, add the use statement to the top of the class:

use Concrete\Core\Feature\Features;

Then, add the appropriate method:

public function getThemeSupportedFeatures()
{
    return [
        Features::BASICS,
        Features::TYPOGRAPHY,
        Features::IMAGERY,
    ];
}

When we reload the page, we get the expected result: we have a JavaScript error in our console due to the lack of some required JavaScript, our gallery block looks strange (because the appropriate CSS is not loaded) and the same is true with our Hero Image. Again, this is to be expected, because we've moved support for this functionality out of the externally loaded fallback assets and into our theme. Now let's actually add the CSS and JavaScript to our theme.

Make sure npm run watch is running

In your theme working directory, start the npm run watch process again so we can make changes to our theme assets and see them in (semi-)realtime.

Add Imagery SCSS Back into Theme

First, let's create a SASS include in assets/scss. Make a directory named features in this location. Then, within this features directory, create another directory named imagery. Leave this second directory empty for the moment.

Next, create an _imagery.scss file within assets/scss/features directory; this will be the place where we implement Imagery functionality.

Finally, open main.scss. It should look something like this:

@import "variables";

@import "@concretecms/bedrock/assets/bedrock/scss/frontend";

We're going to add our custom feature implementation SASS file (which is currently empty) to main.scss, so that the entire file looks like this:

@import "variables";

@import "@concretecms/bedrock/assets/bedrock/scss/frontend";

@import "features/imagery";

(Remember, the @import "features/imagery" statement is actually importing the _imagery.scss file. If you're looking for a lively discussion on this topic, you can check out this StackOverflow post).

So now we're importing our _imagery.scss file, but it's empty. Let's make it do something. Open _imagery.scss and add this:

// Import base stylesheets
@import "@concretecms/bedrock/assets/imagery/scss/frontend/frontend";

Hopefully this looks a little familiar; we're importing the base Imagery feature SCSS from Bedrock directly into our theme. This is actually the same file that's imported for the fallback feature CSS. We're just adding it as is to our theme directly.

This is About Control

In this example we're including the file directly – which may not seem like a huge benefit. Isn't this the same as if we just let the feature remain external? It is, but it doesn't have to be. We don't have to include this file, it simply exists as a convenience (and for the building of fallback assets). If were so inclined, we could leave this file out completely, and re-craft our feature support entirely with custom SCSS. Or we could look into the _frontend.scss file here and pick and choose the SCSS directives we wanted to support. For example, if you look into bedrock/assets/imagery/scss/frontend/frontend you'll see it's structured like this:

// Lightbox
@import 'lightbox/lightbox';

// Gallery
@import 'gallery/gallery';

// Image Slider Block
@import 'responsive-slides';
@import 'image-slider/image-slider';

// Hero Image
@import 'hero-image';

A theme developer is free to copy one or all of these directives into their _imagery.scss file. Want to include the hero image and gallery SCSS, but craft custom functionality for the Lightbox and Image Slider? Include the gallery and Hero Image directives but leave out all others. This is a starting point and meant to be flexible for theme developers.

We'll delve more deeply into a customized solution in the next section.

SASS Variable Support

Here's another benefit to including the SCSS of a feature directly into your theme; since Features are built using Bedrock in the same manner that your theme should be, SCSS variables shared by both will automatically be used appropriate. For example, here's what the gallery block looks like when hovered over using the fallback asset:

#

This is pretty, but this isn't a blue that we're using anywhere in our theme. In fact, it's present because the fallback asset is using the $primary color in Bootstrap 5, which is this blue. However, we've overridden the $primary color in our theme. Once we move the asset into our theme, the shared variable takes over, and we have unification between the blue that we've specified in our theme, and the blue used by the gallery hover:

#

Add Imagery JavaScript Back into Theme

Now that we've added the Imagery feature into our SCSS, let's do the same for JavaScript. Remember, since we've marked Imagery as being supported by this theme, we're also not including the JavaScript fallback asset any longer, which means all of our blocks like Gallery and Image Slider will have problems until we either re-import the fallback JavaScript, or craft our own JavaScript for the block types.

With npm run watch still running, open assets/js/main.js. It should still just have our basic Bedrock JavaScript imported:

import '@concretecms/bedrock/assets/bedrock/js/frontend';

In a similar manner to the SCSS, let's add support for the Imagery feature:

import '@concretecms/bedrock/assets/imagery/js/frontend';

The entire document should now look like

import '@concretecms/bedrock/assets/bedrock/js/frontend';
import '@concretecms/bedrock/assets/imagery/js/frontend';

Once this JavaScript is added back, things should work as they did before. However now the proper blue from our theme is used throughout the gallery, and the fallback assets are no longer included within the header and footer of the page.

Next, we'll add some custom interactions to our Hero Image block within our themes using the Features system.