CTA-USAGE (Veams Components )
src/app/shared/components/cta/templates
Demo Section
Each variation will be presented in the following section.
Readme
Call-To-Action
Description
The CTA component is a powerful one. It can be used as simple link or button component.
But it can also be used as data-js-item
in other components or as data-js-module
.
Usages
When using this the component as data-js-module
the component can fire global events.
That means you can listen in other modules on this event and work with the provided data.
Nice examples for the cta component as data-js-module
are:
- a simple toggler (mobile navigation, search toggler)
- overlay opener with custom data
Example usage
cta-usage.hbs
A <script>
tag is included with a global event handler to produce an alert dialog box when clicking on the button.
Requirements
- @veams/core - Veams Core Framework.
- @veams/query or
jquery
- Veams Query or jQuery. - @veams/component - Veams Component.
Installation
Installation with Veams
veams install component cta
veams -i c cta
Fields
cta.hbs
Settings
Parameter | Type | Default | Description |
---|---|---|---|
settings.ctaButton | Boolean | false |
If set to true a <button> is used instead of an <a> |
settings.ctaContextClass | String | 'default' |
Context class of the CTA |
settings.ctaClass | String | '' |
Modifier classes for the CTA |
settings.ctaTarget | String | '' |
You can define a target when using an <a> tag |
settings.ctaJsItem | String | '' |
You can add this component as a data-js-item |
settings.ctaJsModule | Boolean | false |
If set to true this component is automatically initializing the CTA module |
settings.ctaJsOptions | Object | null |
CTA options object which gets stringified in markup |
Content
Parameter | Type | Description |
---|---|---|
content.ctaTitle | String | A title should be defined when using the <a> tag |
cta__content.hbs
Settings
Parameter | Type | Default | Description |
---|---|---|---|
settings.ctaIcon | Boolean | false |
Renders .cta__icon into the Markup if set to true |
settings.ctaContentJsItem | Boolean | false |
Renders "data-js-item="cta-content" into the Markup if set to true |
Content
Parameter | Type | Description |
---|---|---|
content.ctaContent | String | Content of the CTA |
JavaScript Options
The module gives you the possibility to override default options:
Option | Type | Default | Description |
---|---|---|---|
classes.active | String | 'is-active' |
Click handler like touchstart |
clickHandler | String | 'click' |
Click handler like `touchstart |
closedLabel | String | '' |
Optional label for button while not active |
globalEvent | String | 'cta:click' |
Global event triggered on click |
openedLabel | String | '' |
Optional label for button while active |
selectors.ctaContent | String | '[data-js-item="cta-content"]' |
Element selector for CTA content (used for updating the button text) |
Templates
cta-usage.hbs
{{! WrapWith START: CTA }}
{{#wrapWith "cta" settings=this.settings content=this.content}}
{{> cta__content this.content}}
{{/wrapWith}}
{{! WrapWith END: CTA }}
{{#if this.settings.ctaJsModule}}
<script>
document.addEventListener('DOMContentLoaded', function (e) {
Veams.Vent.subscribe('cta:alert', ({options}) => {
alert(options.data);
});
});
</script>
{{/if}}
cta.hbs
---
publish: false
---
<{{#if options.settings.ctaButton}}button{{else}}a{{/if}}
class="c-cta{{#if options.settings.ctaContextClass}}--{{options.settings.ctaContextClass}}{{else}}--default{{/if}}{{#if options.settings.ctaClass}} {{options.settings.ctaClass}}{{/if}}"
{{#if options.settings.ariaHidden}} aria-hidden="{{options.settings.ariaHidden}}"{{/if}}
data-css="c-cta"
{{#if options.content.ctaTitle}} title="{{options.content.ctaTitle}}"{{/if}}
{{#if options.settings.ctaTarget}} href="{{options.settings.ctaTarget}}"{{/if}}
{{#if options.settings.ctaDownload}} target="_blank"{{/if}}
{{#if options.settings.ctaJsItem}} data-js-item="{{options.settings.ctaJsItem}}"{{/if}}
{{#if options.settings.ctaJsModule}} data-js-module="cta" data-js-options='{{stringify options.settings.jsOptions}}'{{/if}}>
{{{yield}}}
</{{#if options.settings.ctaButton}}button{{else}}a{{/if}}>
cta__content.hbs
---
publish: false
---
{{#isnt settings.ctaIcon false}}
<span class="cta__icon"></span>
{{/isnt}}
<span class="cta__content"{{#if settings.ctaContentJsItem}} data-js-item="cta-content"{{/if}}>
{{content.ctaContent}}
</span>
Data File
cta-bp.hjson
{
"variations": {
"simple": {
"docs": {
"variationName": "Simple CTA link",
"sectionCenter": true
},
"settings": {
"ctaButton": false,
"ctaTarget": "#",
"ctaContextClass": "link",
"ctaClass": "is-link"
},
"content": {
"ctaTitle": "Link Title",
"settings": {
"ctaIcon": true
},
"content": {
"ctaContent": "Link"
}
}
},
"withJs": {
"docs": {
"variationName": "CTA (global event)",
"sectionCenter": true
},
"settings": {
"ctaButton": true,
"ctaTarget": "#",
"ctaContextClass": "default",
"ctaClass": "class",
"ctaJsItem": false,
"ctaJsModule": true,
"jsOptions": {
"globalEvent": "cta:alert",
"data": "My custom text passed by CTA"
}
},
"content": {
"settings": {
"ctaIcon": true
},
"content": {
"ctaContent": "Button"
}
}
}
}
}
Styles
_cta.scss
/* ===================================================
CTA COMPONENT
=================================================== */
$cta-toggle-duration: 250ms;
/* ---------------------------------------------------
Global Styles
--------------------------------------------------- */
[data-css="c-cta"] {
.cta__icon {
}
.cta__content {
}
}
/* ---------------------------------------------------
Context: Default
--------------------------------------------------- */
.c-cta--default {
}
/* ---------------------------------------------------
Context: Anchor Nav
--------------------------------------------------- */
.c-cta--anchor-nav {
position: relative;
z-index: 2;
border: none;
background-color: $color-light;
padding: 10px 20px;
display: inline-block;
font-size: 15px;
font-family: $font-bold;
font-weight: 700;
line-height: (24/15);
color: $color-green-hc-dark;
cursor: pointer;
transition: color $cta-toggle-duration linear;
min-width: 200px;
text-align: center;
@include bp($bp-tablet-p) {
padding: 13px 20px;
}
@include print() {
display: none;
}
&:hover,
&.a11y-focus-key {
color: $color-dark;
.cta__content {
&::before,
&::after {
background-color: $color-dark;
}
}
}
&:focus {
outline: none;
}
&.a11y-focus-key {
@include a11y-focus-key();
}
&.is-active {
.cta__content {
&::before {
transform: rotate(180deg);
}
&::after {
transform: rotate(0deg);
}
}
}
.cta__content {
position: relative;
padding-left: 20px;
display: inline-block;
&::before,
&::after {
@extend %pseudo;
transition: bottom $cta-toggle-duration linear $cta-toggle-duration, transform $cta-toggle-duration ease-out, background-color $cta-toggle-duration linear;
background-color: $color-green;
height: $definition-list-icon-height;
left: 0;
top: 50%;
margin-top: -2px;
width: $definition-list-icon-width;
}
&::after {
transform: rotate(-90deg);
}
}
}
/* ---------------------------------------------------
Context: Image Zoom
--------------------------------------------------- */
.c-cta--image-zoom {
@include hidden-text();
display: none;
position: absolute;
bottom: 0;
right: 0;
width: 40px;
height: 40px;
background-color: rgba($color-dark, 1);
cursor: pointer;
transition: background-color $animation-duration-std $animation-easing-std, border $animation-duration-std $animation-easing-std;
border: 1px solid transparent;
@include bp($bp-tablet-p) {
display: block;
}
@include print() {
display: none;
}
&:hover,
&.a11y-focus-key {
background-color: rgba($color-white, 1);
border: 1px solid $color-green;
&::before {
opacity: 0;
}
&::after {
opacity: 1;
}
}
&::before {
@include pseudo();
@include sprites-icon-expand-white();
@include centering(hv);
position: absolute;
transition: opacity $animation-duration-std $animation-easing-std;
opacity: 1;
}
&::after {
@include pseudo();
@include sprites-icon-expand-green();
@include centering(hv);
position: absolute;
transition: opacity $animation-duration-std $animation-easing-std;
opacity: 0;
}
@include hcm() {
font-size: 16px;
color: $color-dark;
height: 30px;
width: auto;
padding: 5px;
&::before {
background-image: none;
}
&::after {
background-image: none;
}
}
}
Scripts
cta.js
/**
* Represents a button with custom click handlers.
*
* @module CTA
* @version v1.0.0
*
* @author Sebastian Fitzner
* @author Andy Gutsche
*/
/**
* Requirements
*/
import $ from 'jquery';
import Component from '@veams/component';
class CTA extends Component {
/**
* General Properties
*/
// Elements in Markup
$el = $(this.el);
$ctaContent = $(this.options.selectors.ctaContent, this.$el);
/**
* Constructor for our class
*
* @see module.js
*
* @param {Object} obj - Object which is passed to our class
* @param {Object} obj.el - element which will be saved in this.el
* @param {Object} obj.options - options which will be passed in as JSON object
*/
constructor(obj) {
let options = {
classes: {
active: 'is-active'
},
clickHandler: 'click',
closedLabel: '',
globalEvent: 'cta:click',
openedLabel: '',
selectors: {
ctaContent: '[data-js-item="cta-content"]'
}
};
super(obj, options);
}
/** =================================================
* GETTER & SETTER
* ================================================ */
/**
* Get module information
*/
static get info() {
return {
version: '1.0.0',
vc: true,
mod: false // set to true if source was modified in project
};
}
/**
* Get and set the active state.
*
* @param {boolean} state - active state
*/
get active() {
return this._active;
}
set active(state) {
this._active = state;
}
/** =================================================
* EVENTS
* ================================================ */
get events() {
return {
'{{this.options.clickHandler}}': 'onClick'
};
}
/** =================================================
* STANDARD METHODS
* ================================================= */
didMount() {
if (
(this.options.closedLabel && !this.options.openedLabel) ||
(!this.options.closedLabel && this.options.openedLabel)
) {
console.warn('CTA: You have to set closedLabel and openedLabel or none.');
} else {
if (this.options.closedLabel && this.options.openedLabel && !this.$ctaContent.length) {
console.warn(
'CTA: Labels set, but ' +
this.options.selectors.ctaContent +
' not found, please make sure settings.ctaContentJsItem is set to true for c-cta__content.'
);
}
}
if (this.$el.is('.' + this.options.classes.active)) {
this.active = true;
}
}
render() {
return this;
}
/** =================================================
* CUSTOM CTA METHODS
* ================================================= */
/**
* Close method
*
* Remove the active class, set label and trigger global event
*
* @public
*/
close() {
if (this.options.closedLabel) {
this.$ctaContent.text(this.options.closedLabel);
this.$el.attr('title', this.options.closedLabel);
}
this.$el.removeClass(this.options.classes.active);
this.$el.attr('aria-expanded', false);
this.active = false;
}
/**
* Open method
*
* Add the active class, set label and trigger global event
*
* @public
*/
open() {
if (this.options.openedLabel) {
this.$ctaContent.text(this.options.openedLabel);
this.$el.attr('title', this.options.openedLabel);
}
this.$el.addClass(this.options.classes.active);
this.$el.attr('aria-expanded', true);
this.active = true;
}
/**
* Click event method
*
* This method should be overridden when you want to use the button view
*
* @param {event} e - event object
*/
onClick(e) {
e.preventDefault();
if (typeof this.clickHandler === 'function') {
if (this.active) {
this.close();
} else {
this.open();
}
this.clickHandler.apply(this, arguments);
} else {
console.warn(
'CTA: You need to inherit from ' +
this +
' and override the onClick method or pass a function to ' +
this +
'.clickHandler !'
);
}
}
/**
* Click handler
*
* This method is public and can be overridden by
* other instances to support a generic button module.
*
* @public
*/
clickHandler() {
this.context.Vent.trigger(this.options.globalEvent, {
el: this.el,
isActive: this.active,
options: this.options
});
}
}
export default CTA;
HTML Output
Simple CTA link
<a class="c-cta--link is-link" data-css="c-cta" title="Link Title" href="#">
<span class="cta__icon"></span>
<span class="cta__content">
Link
</span>
</a>
CTA (global event)
<button class="c-cta--default class" data-css="c-cta" href="#" data-js-module="cta" data-js-options='{"globalEvent":"cta:alert","data":"My custom text passed by CTA"}'>
<span class="cta__icon"></span>
<span class="cta__content">
Button
</span>
</button>
<script>
document.addEventListener('DOMContentLoaded', function(e) {
Veams.Vent.subscribe('cta:alert', ({
options
}) => {
alert(options.data);
});
});
</script>