CTA-USAGE (Veams Components )

src/app/shared/components/cta/templates

Demo Section

Each variation will be presented in the following section.

Simple CTA link

Link

CTA (global event)


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


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='{&quot;globalEvent&quot;:&quot;cta:alert&quot;,&quot;data&quot;:&quot;My custom text passed by CTA&quot;}'>
	<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>

Wonach suchst du?