From 91357f463c621008595100974f2ae20b3662eebe Mon Sep 17 00:00:00 2001 From: Nicole Karhoff <45244877+nkarhoff@users.noreply.github.com> Date: Tue, 21 May 2024 10:39:47 -0400 Subject: [PATCH] TW29486487 Animated Stats (#39) * Add animated stat pattern * Update to move item to Columns component --- .../animated-stat.ui_patterns.yml | 27 ++++++++ .../animated-stat/css/animated-stat.css | 21 ++++++ ...--paragraph--field-animated-stat.html.twig | 66 +++++++++++++++++++ .../animated-stat/js/animated-statistics.js | 51 ++++++++++++++ .../pattern-animated-stat.html.twig | 6 ++ 5 files changed, 171 insertions(+) create mode 100644 templates/patterns/animated-stat/animated-stat.ui_patterns.yml create mode 100644 templates/patterns/animated-stat/css/animated-stat.css create mode 100644 templates/patterns/animated-stat/field--paragraph--field-animated-stat.html.twig create mode 100644 templates/patterns/animated-stat/js/animated-statistics.js create mode 100644 templates/patterns/animated-stat/pattern-animated-stat.html.twig diff --git a/templates/patterns/animated-stat/animated-stat.ui_patterns.yml b/templates/patterns/animated-stat/animated-stat.ui_patterns.yml new file mode 100644 index 0000000..fdd2938 --- /dev/null +++ b/templates/patterns/animated-stat/animated-stat.ui_patterns.yml @@ -0,0 +1,27 @@ +animated-stat: + label: "Animated Stat" + description: "A statistics that animates counting up when it comes into view." + category: "Stats" + variants: + default: + label: "Default" + fields: + stat_description: + type: "textfield" + label: "Stat Description" + stat_number: + type: "integer" + label: "Stat Number" + stat_prefix: + type: "textfield" + label: "Stat Prefix" + stat_suffix: + type: "textfield" + label: "Stat Suffix" + libraries: + - animated-stat: + js: + js/animated-statistics.js: {} + css: + theme: + css/animated-stat.css: {} diff --git a/templates/patterns/animated-stat/css/animated-stat.css b/templates/patterns/animated-stat/css/animated-stat.css new file mode 100644 index 0000000..a6353d2 --- /dev/null +++ b/templates/patterns/animated-stat/css/animated-stat.css @@ -0,0 +1,21 @@ +/* Individual Stat */ +.stat_paragraph.animated { + flex: 1; +} + +.stat_paragraph.animated .stat { + font-size: 3.5rem; + font-weight: 400; + line-height: 112%; + display: flex; + align-items: center; + justify-content: center; +} +.stat_paragraph.animated .stat_description { + display: flex; + flex-direction: column; + align-items: center; +} +.stat_suffix { + margin-left: 10px; +} diff --git a/templates/patterns/animated-stat/field--paragraph--field-animated-stat.html.twig b/templates/patterns/animated-stat/field--paragraph--field-animated-stat.html.twig new file mode 100644 index 0000000..9fb9456 --- /dev/null +++ b/templates/patterns/animated-stat/field--paragraph--field-animated-stat.html.twig @@ -0,0 +1,66 @@ +{# +/** + * @file + * Default theme implementation for a field. + * + * To override output, copy the "field.html.twig" from the templates directory + * to your theme's directory and customize it, just like customizing other + * Drupal templates such as page.html.twig or node.html.twig. + * + * Instead of overriding the theming for all fields, you can also just override + * theming for a subset of fields using + * @link themeable Theme hook suggestions. @endlink For example, + * here are some theme hook suggestions that can be used for a field_foo field + * on an article node type: + * - field--node--field-foo--article.html.twig + * - field--node--field-foo.html.twig + * - field--node--article.html.twig + * - field--field-foo.html.twig + * - field--text-with-summary.html.twig + * - field.html.twig + * + * Available variables: + * - attributes: HTML attributes for the containing element. + * - label_hidden: Whether to show the field label or not. + * - title_attributes: HTML attributes for the title. + * - label: The label for the field. + * - multiple: TRUE if a field can contain multiple items. + * - items: List of all the field items. Each item contains: + * - attributes: List of HTML attributes for each item. + * - content: The field item's content. + * - entity_type: The entity type to which the field belongs. + * - field_name: The name of the field. + * - field_type: The type of the field. + * - label_display: The display settings for the label. + * + * @see template_preprocess_field() + * + * @ingroup themeable + */ +#} +{% + set title_classes = [ + 'field--label', + 'field--label--' ~ label_display|clean_class, + label_display == 'visually_hidden' ? 'visually-hidden', + label_display == 'inline' ? 'float-start', + label_display == 'inline' ? 'pe-2', + 'fw-bold', + ] +%} +{% set field_items_attributes = create_attribute({ + 'class': [ + 'animated-statistics', + multiple and label_display == 'inline' ? 'float-start', + ] +}) %} + + {% if not label_hidden %} + {{ label }} + {% endif %} + + {% for item in items %} + {{ item.content }} + {% endfor %} + + diff --git a/templates/patterns/animated-stat/js/animated-statistics.js b/templates/patterns/animated-stat/js/animated-statistics.js new file mode 100644 index 0000000..af7e1a5 --- /dev/null +++ b/templates/patterns/animated-stat/js/animated-statistics.js @@ -0,0 +1,51 @@ +/** + * Animated Stats JS. + * @file + */ +(function (Drupal, drupalSettings) { + /* + * Animate Stats. + */ + Drupal.behaviors.animateStat = { + attach: function (context) { + + const elements = document.querySelectorAll('.stat_paragraph'); + + elements.forEach(function(element) { + const observer = new IntersectionObserver(entries => { + if (entries[0].isIntersecting) { + setTimeout(function() { + const counters = element.querySelectorAll('.stat_number'); + const speed = 500; + + counters.forEach( counter => { + const animate = () => { + const value = +counter.getAttribute('value'); + const data = +counter.innerText; + + const time = value / speed; + if (data < value) { + if (value > 999) { + counter.innerText = Math.ceil(data + time + 100); + setTimeout(animate, 1); + } else { + counter.innerText = Math.ceil(data + time); + setTimeout(animate, 1); + } + } else { + counter.innerText = value; + } + } + animate(); + }); + }, 1000); + } + }); + observer.observe( element ); + }); + + + + }, + }; + })(Drupal, drupalSettings); diff --git a/templates/patterns/animated-stat/pattern-animated-stat.html.twig b/templates/patterns/animated-stat/pattern-animated-stat.html.twig new file mode 100644 index 0000000..83dff32 --- /dev/null +++ b/templates/patterns/animated-stat/pattern-animated-stat.html.twig @@ -0,0 +1,6 @@ +
+
+
{{ stat_prefix|render|striptags }}
0
{% if stat_suffix is not empty %}
{{ stat_suffix|render|striptags }}
{% endif %} +
+
{{ stat_description|render|striptags }}
+