Develop Front End Components with AEM Coral UI

Published Apr 15, 2020


Coral UI is a library of touch-first web components, used to ease the work of a front end developer. All components build in Coral UI are simple to use and responsive. These components help to keep the look and style of the platform uniform.


You can find Coral UI cilentlibs under:

Coral UI2: /libs/clientlibs/granite/coralui2

Coral UI3: /libs/clientlibs/granite/coralui3

Also, here are the clientlibs categories for Coral UI:

Coral UI2:,, coralui2

Coral UI3:, coralui3



🤔 Why use Coral UI?

Non-overlay safe (
Non-overlay safe (

We can add different components on any AEM UI page/toolbar using Granite Server Side Components. We can simply overlay the respective node in AEM and add a custom component node in it (checkout for more information).

But, Some nodes in AEM are not safe to overlay (granite:FinalArea, granite:InternalArea) like /libs/cq/inbox/content/inbox, /libs/cq/workflow/admin/console/content/instances, etc 😥.

So, to add our custom components like buttons, drop-downs, text fields, etc., we can utilize the existing Coral UI library and initialize these components using javascript and then add respective toolbar clientlibs category to load our js with the OOTB clientlibs 😊.

Even you can override existing js event handlers with this and add some extra features to buttons or components 🤩.

In this tutorial, we will add two buttons in the AEM Inbox action bar.


Add buttons in the AEM Inbox action bar

  • Step 1: Get the clientlibs category of the target page. We need to create a clientlibs folder in our project with this category. So, it will get loaded after the targeted page’s clientlibs.


  • Step 2: Create a clientlibs folder with the category received from Step 1

Here, I have created the folder with categories(String[]) = cq.inbox.gui, which is same as the category we received in Step 1
Here, I have created the folder with categories(String[]) = cq.inbox.gui, which is same as the category we received in Step 1

  • Step 3: Start Coding with the Coral UI library! So, before starting with actual code we will understand the folder structure and what each file is for. Check the following image of the folder structure:

    Project file structure
    Project file structure

    1. actions: This folder has JS code to handle button click events. This is based on Granite UI client-side JS components called foundation-collection-action.
    2. buttons: It contains the Coral UI library code to initialize button components.
    3. init.js: It initializes the buttons’ code written in the above folder.
    4. show-hide.js: As we are developing these buttons for assets, this show-hide.js handles the item select event in AEM Inbox and show the buttons if the item’s payload in under DAM, else hide the buttons.


Now, let’s talk about the individual code:


  1. foundation-collection-action:
(function(window, $, URITemplate) { 'use strict' $(window) .adaptTo('foundation-registry') .register('foundation.collection.action.action', { name: '', handler: function(name, el, config, collection, selections) { let linkAttributeName = let payloadLink = $(selections) .data(linkAttributeName) .replace(/\/assetdetails.html|\/jcr:content.*/, '') let url = payloadLink if ( {, } else { window.location = url } }, }) })(window, Granite.$, Granite.URITemplate)


Granite UI has a client-side JS component called foundation-collection-action. foundation-collection-action is a control to perform an action related to foundation-selections. So, when you select any item in Inbox this event can be handled using foundation-collection-action to get selected items easily. handler function triggers on the “click” event and passes the selected items ( selections ) and config (a configuration stored in the button as JSON in the HTML data attribute), which has an action name and other parameters to read data from selected items. For the above code linkAttributeName has a value payloadLink stored in button configuration to read data from Inbox item that is payload link of the selected item (check button configuration code). The action handler will be called when the name matches. A chain of registered actions is created using LIFO (last in, first out) algorithm. So, you can override the default handler easily, just by registering custom handler code later.

Payload link data attribute
Payload link data attribute

2. Coral UI Button:

let downloadAsset = () => { //Create Coral Button Structure: let button = new Coral.Button().set({ label: { innerHTML: 'Download Asset', }, variant: 'quiet', icon: 'download', iconSize: 'S', }) //Action config to handle click event /** * activeSelectionCount: Visibilty config for single/multiple select * if single then visble for single select only * data: Data config to for callback action */ let actionConfig = { activeSelectionCount: 'single', action: '', data: { linkAttributeName: 'payloadLink', target: '_blank', }, } $(button).attr( 'data-foundation-collection-action', JSON.stringify(actionConfig) ) //Add Grnaite tracking features $(button).attr('trackingfeature') $(button).attr('trackingelement', 'download asset') $(button).attr('tracking', 'ON') //Add exiting inbox classes to align & style button properly: //cq-inbox-asset is addded to track element for show/hide functionality $(button).addClass( 'betty-ActionBar-item ' + 'cq-inbox-asset ' + 'foundation-collection-action ' + 'coral-Button--graniteActionBar' ) return button }


Coral UI has many components and all can be instantiated easily with JS, without adding a hardcoded string of HTML. Learn more about the Coral Button component here.


3. Coral UI Action Bar (init.js):

$(document).ready(function() { let actionBar = document.getElementsByClassName('betty-ActionBar')[0] //wait till the actionbar is ready Coral.commons.ready(actionBar, function() { //Get item list for left buttons let leftItems = actionBar.primary.items //Add custom buttons to the action bar leftItems.add({}).appendChild(viewAssetProps()) leftItems.add({}).appendChild(downloadAsset()) }) })


To add these buttons in the Inbox action bar we can use the existing appendChild() method and pass the respective buttons. leftItems are the buttons which we see on the left side of the action bar like complete, step back, etc. Here, Coral.commons.ready() checks whether Coral components and all nested components are ready, which assures their _initialize and _render methods have been called. If so, the provided callback function is executed.


4. Hide buttons for payload other than assets:

$(document).on('click', '.foundation-collection-item', function(item) { let assetPath = '/content/dam' let selector = '.foundation-selections-item' let linkAttributeName = 'payloadLink' let row = $( let payloadPath = $(row).data(linkAttributeName) if (payloadPath && payloadPath.indexOf(assetPath) !== -1) { $('.cq-inbox-asset').removeClass('foundation-collection-action-hidden') } else { $('.cq-inbox-asset').addClass('foundation-collection-action-hidden') } })


This is a simple “click” event handler which gets triggered when we click on the item’s checkbox. As these buttons are specifically for assets, if the selected item payload is not under /content/dam then, these buttons should not be visible.



Coral UI is a very useful library while developing the front end components which are part of AEM UI. This makes components uniform throughout the platform. Also, code management gets easy as many lines of boilerplate code are avoided.





Check my other stories here



  1. Coral UI
  2. Granite UI