├── README.md ├── config └── install │ ├── paragraphs.paragraphs_type.xeno_hero.yml │ ├── field.storage.paragraph.xeno_offset.yml │ ├── field.storage.paragraph.xeno_content.yml │ ├── field.field.paragraph.xeno_hero.xeno_zoom.yml │ ├── field.field.paragraph.xeno_hero.xeno_invert.yml │ ├── field.storage.paragraph.xeno_invert.yml │ ├── field.field.paragraph.xeno_hero.xeno_parallax.yml │ ├── field.field.paragraph.xeno_hero.xeno_offset.yml │ ├── field.field.paragraph.xeno_hero.xeno_overlay.yml │ ├── field.storage.paragraph.xeno_background_image.yml │ ├── field.field.paragraph.xeno_hero.xeno_content.yml │ ├── field.storage.paragraph.xeno_zoom.yml │ ├── field.storage.paragraph.xeno_parallax.yml │ ├── field.storage.paragraph.xeno_overlay.yml │ ├── field.field.paragraph.xeno_hero.xeno_background_image.yml │ ├── core.entity_view_display.paragraph.xeno_hero.default.yml │ └── core.entity_form_display.paragraph.xeno_hero.default.yml ├── xeno_hero.info.yml ├── xeno_hero.libraries.yml ├── xeno_hero.module ├── composer.json ├── xeno_hero.install ├── js └── xeno-hero.js ├── css └── xeno-hero.css ├── templates └── paragraph--xeno-hero.html.twig └── LICENSE.txt /README.md: -------------------------------------------------------------------------------- 1 | # xeno_hero 2 | Drupal 8 module that creates a Hero Paragraphs bundle. 3 | -------------------------------------------------------------------------------- /config/install/paragraphs.paragraphs_type.xeno_hero.yml: -------------------------------------------------------------------------------- 1 | langcode: en 2 | status: true 3 | dependencies: { } 4 | id: xeno_hero 5 | label: Hero 6 | behavior_plugins: { } 7 | -------------------------------------------------------------------------------- /xeno_hero.info.yml: -------------------------------------------------------------------------------- 1 | name: Xeno Hero Paragraph Bundle 2 | type: module 3 | core_version_requirement: ^8 || ^9 4 | description: A reusable Hero Paragraph bundle with parallax and an overlay. 5 | package: Paragraphs 6 | dependencies: 7 | - paragraphs 8 | -------------------------------------------------------------------------------- /xeno_hero.libraries.yml: -------------------------------------------------------------------------------- 1 | xeno-hero: 2 | css: 3 | component: 4 | css/xeno-hero.css: 5 | minified: false 6 | js: 7 | js/xeno-hero.js: 8 | minified: false 9 | dependencies: 10 | - core/jquery 11 | - core/drupal 12 | -------------------------------------------------------------------------------- /xeno_hero.module: -------------------------------------------------------------------------------- 1 | [ 14 | 'base hook' => 'paragraph', 15 | ], 16 | ]; 17 | } 18 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "xenomedia/xeno_hero", 3 | "type": "drupal-custom-module", 4 | "description": "Drupal 8 module that creates a Hero Paragraphs bundle.", 5 | "keywords": ["Drupal"], 6 | "license": "GPL-2.0+", 7 | "homepage": "https://github.com/xenomedia/xeno_hero", 8 | "support": { 9 | "issues": "https://github.com/xenomedia/xeno_hero/issues", 10 | "source": "https://github.com/xenomedia/xeno_hero" 11 | }, 12 | "require": { } 13 | } 14 | -------------------------------------------------------------------------------- /config/install/field.storage.paragraph.xeno_offset.yml: -------------------------------------------------------------------------------- 1 | langcode: en 2 | status: true 3 | dependencies: 4 | module: 5 | - paragraphs 6 | id: paragraph.xeno_offset 7 | field_name: xeno_offset 8 | entity_type: paragraph 9 | type: string 10 | settings: 11 | max_length: 255 12 | is_ascii: false 13 | case_sensitive: false 14 | module: core 15 | locked: false 16 | cardinality: 1 17 | translatable: true 18 | indexes: { } 19 | persist_with_no_fields: false 20 | custom_storage: false 21 | -------------------------------------------------------------------------------- /config/install/field.storage.paragraph.xeno_content.yml: -------------------------------------------------------------------------------- 1 | langcode: en 2 | status: true 3 | dependencies: 4 | module: 5 | - entity_reference_revisions 6 | - paragraphs 7 | id: paragraph.xeno_content 8 | field_name: xeno_content 9 | entity_type: paragraph 10 | type: entity_reference_revisions 11 | settings: 12 | target_type: paragraph 13 | module: entity_reference_revisions 14 | locked: false 15 | cardinality: 6 16 | translatable: true 17 | indexes: { } 18 | persist_with_no_fields: false 19 | custom_storage: false 20 | -------------------------------------------------------------------------------- /config/install/field.field.paragraph.xeno_hero.xeno_zoom.yml: -------------------------------------------------------------------------------- 1 | langcode: en 2 | status: true 3 | dependencies: 4 | config: 5 | - field.storage.paragraph.xeno_zoom 6 | - paragraphs.paragraphs_type.xeno_hero 7 | module: 8 | - options 9 | id: paragraph.xeno_hero.xeno_zoom 10 | field_name: xeno_zoom 11 | entity_type: paragraph 12 | bundle: xeno_hero 13 | label: Zoom 14 | description: '' 15 | required: false 16 | translatable: false 17 | default_value: { } 18 | default_value_callback: '' 19 | settings: { } 20 | field_type: list_string 21 | -------------------------------------------------------------------------------- /config/install/field.field.paragraph.xeno_hero.xeno_invert.yml: -------------------------------------------------------------------------------- 1 | langcode: en 2 | status: true 3 | dependencies: 4 | config: 5 | - field.storage.paragraph.xeno_invert 6 | - paragraphs.paragraphs_type.xeno_hero 7 | module: 8 | - options 9 | id: paragraph.xeno_hero.xeno_invert 10 | field_name: xeno_invert 11 | entity_type: paragraph 12 | bundle: xeno_hero 13 | label: Invert 14 | description: '' 15 | required: false 16 | translatable: false 17 | default_value: { } 18 | default_value_callback: '' 19 | settings: { } 20 | field_type: list_string 21 | -------------------------------------------------------------------------------- /config/install/field.storage.paragraph.xeno_invert.yml: -------------------------------------------------------------------------------- 1 | langcode: en 2 | status: true 3 | dependencies: 4 | module: 5 | - options 6 | - paragraphs 7 | id: paragraph.xeno_invert 8 | field_name: xeno_invert 9 | entity_type: paragraph 10 | type: list_string 11 | settings: 12 | allowed_values: 13 | - 14 | value: invert 15 | label: Invert 16 | allowed_values_function: '' 17 | module: options 18 | locked: false 19 | cardinality: 1 20 | translatable: true 21 | indexes: { } 22 | persist_with_no_fields: false 23 | custom_storage: false 24 | -------------------------------------------------------------------------------- /config/install/field.field.paragraph.xeno_hero.xeno_parallax.yml: -------------------------------------------------------------------------------- 1 | langcode: en 2 | status: true 3 | dependencies: 4 | config: 5 | - field.storage.paragraph.xeno_parallax 6 | - paragraphs.paragraphs_type.xeno_hero 7 | module: 8 | - options 9 | id: paragraph.xeno_hero.xeno_parallax 10 | field_name: xeno_parallax 11 | entity_type: paragraph 12 | bundle: xeno_hero 13 | label: Parallax 14 | description: '' 15 | required: false 16 | translatable: false 17 | default_value: { } 18 | default_value_callback: '' 19 | settings: { } 20 | field_type: list_string 21 | -------------------------------------------------------------------------------- /config/install/field.field.paragraph.xeno_hero.xeno_offset.yml: -------------------------------------------------------------------------------- 1 | langcode: en 2 | status: true 3 | dependencies: 4 | config: 5 | - field.storage.paragraph.xeno_offset 6 | - paragraphs.paragraphs_type.xeno_hero 7 | id: paragraph.xeno_hero.field_offset 8 | field_name: xeno_offset 9 | entity_type: paragraph 10 | bundle: xeno_hero 11 | label: Offset 12 | description: 'Enter a positive number to modify the position of the background image.' 13 | required: false 14 | translatable: false 15 | default_value: { } 16 | default_value_callback: '' 17 | settings: { } 18 | field_type: string 19 | -------------------------------------------------------------------------------- /config/install/field.field.paragraph.xeno_hero.xeno_overlay.yml: -------------------------------------------------------------------------------- 1 | langcode: en 2 | status: true 3 | dependencies: 4 | config: 5 | - field.storage.paragraph.xeno_overlay 6 | - paragraphs.paragraphs_type.xeno_hero 7 | module: 8 | - options 9 | id: paragraph.xeno_hero.xeno_overlay 10 | field_name: xeno_overlay 11 | entity_type: paragraph 12 | bundle: xeno_hero 13 | label: Overlay 14 | description: '' 15 | required: false 16 | translatable: false 17 | default_value: 18 | - 19 | value: '0' 20 | default_value_callback: '' 21 | settings: { } 22 | field_type: list_string 23 | -------------------------------------------------------------------------------- /config/install/field.storage.paragraph.xeno_background_image.yml: -------------------------------------------------------------------------------- 1 | langcode: en 2 | status: true 3 | dependencies: 4 | module: 5 | - file 6 | - image 7 | - paragraphs 8 | id: paragraph.xeno_background_image 9 | field_name: xeno_background_image 10 | entity_type: paragraph 11 | type: image 12 | settings: 13 | uri_scheme: public 14 | default_image: 15 | uuid: '' 16 | alt: '' 17 | title: '' 18 | width: null 19 | height: null 20 | target_type: file 21 | display_field: false 22 | display_default: false 23 | module: image 24 | locked: false 25 | cardinality: 1 26 | translatable: true 27 | indexes: { } 28 | persist_with_no_fields: false 29 | custom_storage: false 30 | -------------------------------------------------------------------------------- /config/install/field.field.paragraph.xeno_hero.xeno_content.yml: -------------------------------------------------------------------------------- 1 | langcode: en 2 | status: true 3 | dependencies: 4 | config: 5 | - field.storage.paragraph.xeno_content 6 | - paragraphs.paragraphs_type.xeno_hero 7 | module: 8 | - entity_reference_revisions 9 | id: paragraph.xeno_hero.xeno_content 10 | field_name: xeno_content 11 | entity_type: paragraph 12 | bundle: xeno_hero 13 | label: Content 14 | description: '' 15 | required: false 16 | translatable: false 17 | default_value: { } 18 | default_value_callback: '' 19 | settings: 20 | handler: 'default:paragraph' 21 | handler_settings: 22 | target_bundles: null 23 | target_bundles_drag_drop: 24 | xeno_hero: 25 | weight: 2 26 | enabled: false 27 | field_type: entity_reference_revisions 28 | -------------------------------------------------------------------------------- /config/install/field.storage.paragraph.xeno_zoom.yml: -------------------------------------------------------------------------------- 1 | langcode: en 2 | status: true 3 | dependencies: 4 | module: 5 | - options 6 | - paragraphs 7 | id: paragraph.xeno_zoom 8 | field_name: xeno_zoom 9 | entity_type: paragraph 10 | type: list_string 11 | settings: 12 | allowed_values: 13 | - 14 | value: '6' 15 | label: 'Slowest' 16 | - 17 | value: '5' 18 | label: 'Slower' 19 | - 20 | value: '4' 21 | label: 'Slow' 22 | - 23 | value: '3' 24 | label: 'Fast' 25 | - 26 | value: '2' 27 | label: 'Faster' 28 | - 29 | value: '1' 30 | label: 'Fastest' 31 | allowed_values_function: '' 32 | module: options 33 | locked: false 34 | cardinality: 1 35 | translatable: true 36 | indexes: { } 37 | persist_with_no_fields: false 38 | custom_storage: false 39 | -------------------------------------------------------------------------------- /config/install/field.storage.paragraph.xeno_parallax.yml: -------------------------------------------------------------------------------- 1 | langcode: en 2 | status: true 3 | dependencies: 4 | module: 5 | - options 6 | - paragraphs 7 | id: paragraph.xeno_parallax 8 | field_name: xeno_parallax 9 | entity_type: paragraph 10 | type: list_string 11 | settings: 12 | allowed_values: 13 | - 14 | value: '6' 15 | label: 'Slowest' 16 | - 17 | value: '5' 18 | label: 'Slower' 19 | - 20 | value: '4' 21 | label: 'Slow' 22 | - 23 | value: '3' 24 | label: 'Fast' 25 | - 26 | value: '2' 27 | label: 'Faster' 28 | - 29 | value: '1' 30 | label: 'Fastest' 31 | allowed_values_function: '' 32 | module: options 33 | locked: false 34 | cardinality: 1 35 | translatable: true 36 | indexes: { } 37 | persist_with_no_fields: false 38 | custom_storage: false 39 | -------------------------------------------------------------------------------- /config/install/field.storage.paragraph.xeno_overlay.yml: -------------------------------------------------------------------------------- 1 | langcode: en 2 | status: true 3 | dependencies: 4 | module: 5 | - options 6 | - paragraphs 7 | id: paragraph.xeno_overlay 8 | field_name: xeno_overlay 9 | entity_type: paragraph 10 | type: list_string 11 | settings: 12 | allowed_values: 13 | - 14 | value: '9' 15 | label: '9 - Darkest' 16 | - 17 | value: '8' 18 | label: '8' 19 | - 20 | value: '7' 21 | label: '7' 22 | - 23 | value: '6' 24 | label: '6' 25 | - 26 | value: '5' 27 | label: '5' 28 | - 29 | value: '4' 30 | label: '4' 31 | - 32 | value: '3' 33 | label: '3' 34 | - 35 | value: '2' 36 | label: '2' 37 | - 38 | value: '1' 39 | label: '1 - Lightest' 40 | allowed_values_function: '' 41 | module: options 42 | locked: false 43 | cardinality: 1 44 | translatable: true 45 | indexes: { } 46 | persist_with_no_fields: false 47 | custom_storage: false 48 | -------------------------------------------------------------------------------- /config/install/field.field.paragraph.xeno_hero.xeno_background_image.yml: -------------------------------------------------------------------------------- 1 | langcode: en 2 | status: true 3 | dependencies: 4 | config: 5 | - field.storage.paragraph.xeno_background_image 6 | - paragraphs.paragraphs_type.xeno_hero 7 | module: 8 | - image 9 | id: paragraph.xeno_hero.xeno_background_image 10 | field_name: xeno_background_image 11 | entity_type: paragraph 12 | bundle: xeno_hero 13 | label: 'Background Image' 14 | description: '' 15 | required: false 16 | translatable: false 17 | default_value: { } 18 | default_value_callback: '' 19 | settings: 20 | file_directory: 'hero/[date:custom:Y]-[date:custom:m]' 21 | file_extensions: 'png gif jpg jpeg' 22 | max_filesize: '' 23 | max_resolution: '' 24 | min_resolution: '' 25 | alt_field: true 26 | alt_field_required: true 27 | title_field: false 28 | title_field_required: false 29 | default_image: 30 | uuid: '' 31 | alt: '' 32 | title: '' 33 | width: null 34 | height: null 35 | handler: 'default:file' 36 | handler_settings: { } 37 | field_type: image 38 | -------------------------------------------------------------------------------- /xeno_hero.install: -------------------------------------------------------------------------------- 1 | save(); 23 | } 24 | // Create field instance. 25 | $field_yml = Yaml::parse(file_get_contents($path . '/config/install/field.field.paragraph.xeno_hero.xeno_offset.yml')); 26 | if (!FieldConfig::loadByName($field_yml['entity_type'], $field_yml['bundle'], $field_yml['field_name'])) { 27 | FieldConfig::create($field_yml)->save(); 28 | } 29 | 30 | // Send message to updater. 31 | $message = t('Offset field added to the hero bundle. It allows you to modify the position of the background image. Navigate to the Manage form display and Manage display for Hero to enable the offset field.'); 32 | return $message; 33 | } 34 | -------------------------------------------------------------------------------- /js/xeno-hero.js: -------------------------------------------------------------------------------- 1 | (function ($, Drupal) { 2 | 3 | "use strict"; 4 | 5 | // Makes the parallax function. 6 | function parallaxIt() { 7 | 8 | // Create variables. 9 | var $fwindow = $(window); 10 | var scrollTop = window.pageYOffset || document.documentElement.scrollTop; 11 | 12 | // Adds on window scroll event. 13 | $fwindow.on('scroll resize', function() { 14 | scrollTop = window.pageYOffset || document.documentElement.scrollTop; 15 | }); 16 | 17 | // For each of background parallax elements. 18 | $('.paragraph--type--xeno-hero .paragraph--type--xeno-hero__image').each(function(){ 19 | var $backgroundObj = $(this); 20 | var yPos; 21 | var coords; 22 | var speed = $backgroundObj.parent().attr('data-speed'); 23 | 24 | $backgroundObj.css('background-image', 'url(' + $backgroundObj.find('img').attr('src') + ')'); 25 | 26 | $fwindow.on('scroll resize', function() { 27 | var docViewTop = $(window).scrollTop(); 28 | var docViewBottom = docViewTop + $(window).height(); 29 | var offset = $backgroundObj.parent().attr('data-offset'); 30 | if (offset === undefined) { 31 | offset = 0; 32 | } 33 | else { 34 | offset = parseInt(offset); 35 | } 36 | 37 | if ($backgroundObj.offset().top < docViewBottom) { 38 | yPos = -((docViewTop / speed) + offset); 39 | coords = '50% '+ yPos + 'px'; 40 | 41 | $backgroundObj.css({ backgroundPosition: coords }); 42 | } 43 | }); 44 | }); 45 | 46 | // Triggers the window scroll for refresh. 47 | $fwindow.trigger('scroll'); 48 | }; 49 | 50 | parallaxIt(); 51 | 52 | })(jQuery, Drupal); 53 | -------------------------------------------------------------------------------- /config/install/core.entity_view_display.paragraph.xeno_hero.default.yml: -------------------------------------------------------------------------------- 1 | langcode: en 2 | status: true 3 | dependencies: 4 | config: 5 | - field.field.paragraph.xeno_hero.xeno_background_image 6 | - field.field.paragraph.xeno_hero.xeno_content 7 | - field.field.paragraph.xeno_hero.xeno_invert 8 | - field.field.paragraph.xeno_hero.xeno_offset 9 | - field.field.paragraph.xeno_hero.xeno_overlay 10 | - field.field.paragraph.xeno_hero.xeno_parallax 11 | - paragraphs.paragraphs_type.xeno_hero 12 | module: 13 | - entity_reference_revisions 14 | - image 15 | - options 16 | id: paragraph.xeno_hero.default 17 | targetEntityType: paragraph 18 | bundle: xeno_hero 19 | mode: default 20 | content: 21 | xeno_background_image: 22 | weight: 0 23 | label: hidden 24 | settings: 25 | image_style: '' 26 | image_link: '' 27 | third_party_settings: { } 28 | type: image 29 | xeno_content: 30 | type: entity_reference_revisions_entity_view 31 | weight: 1 32 | label: hidden 33 | settings: 34 | view_mode: default 35 | link: '' 36 | third_party_settings: { } 37 | xeno_invert: 38 | weight: 4 39 | label: hidden 40 | settings: { } 41 | third_party_settings: { } 42 | type: list_key 43 | xeno_offset: 44 | weight: 6 45 | label: above 46 | settings: 47 | link_to_entity: false 48 | third_party_settings: { } 49 | type: string 50 | region: content 51 | xeno_overlay: 52 | weight: 3 53 | label: hidden 54 | settings: { } 55 | third_party_settings: { } 56 | type: list_key 57 | xeno_parallax: 58 | weight: 2 59 | label: hidden 60 | settings: { } 61 | third_party_settings: { } 62 | type: list_key 63 | xeno_zoom: 64 | weight: 5 65 | label: hidden 66 | settings: { } 67 | third_party_settings: { } 68 | type: list_key 69 | hidden: { } 70 | -------------------------------------------------------------------------------- /config/install/core.entity_form_display.paragraph.xeno_hero.default.yml: -------------------------------------------------------------------------------- 1 | langcode: en 2 | status: true 3 | dependencies: 4 | config: 5 | - field.field.paragraph.xeno_hero.xeno_background_image 6 | - field.field.paragraph.xeno_hero.xeno_content 7 | - field.field.paragraph.xeno_hero.xeno_invert 8 | - field.field.paragraph.xeno_hero.xeno_offset 9 | - field.field.paragraph.xeno_hero.xeno_overlay 10 | - field.field.paragraph.xeno_hero.xeno_parallax 11 | - field.field.paragraph.xeno_hero.xeno_zoom 12 | - image.style.thumbnail 13 | - paragraphs.paragraphs_type.xeno_hero 14 | module: 15 | - image 16 | - paragraphs 17 | id: paragraph.xeno_hero.default 18 | targetEntityType: paragraph 19 | bundle: xeno_hero 20 | mode: default 21 | content: 22 | xeno_background_image: 23 | weight: 0 24 | settings: 25 | progress_indicator: throbber 26 | preview_image_style: thumbnail 27 | third_party_settings: { } 28 | type: image_image 29 | xeno_content: 30 | type: entity_reference_paragraphs 31 | weight: 1 32 | settings: 33 | title: Paragraph 34 | title_plural: Paragraphs 35 | edit_mode: closed 36 | add_mode: dropdown 37 | form_display_mode: default 38 | default_paragraph_type: '' 39 | third_party_settings: { } 40 | xeno_invert: 41 | weight: 4 42 | settings: { } 43 | third_party_settings: { } 44 | type: options_select 45 | xeno_offset: 46 | weight: 7 47 | settings: 48 | size: 60 49 | placeholder: '' 50 | third_party_settings: { } 51 | type: string_textfield 52 | region: content 53 | xeno_overlay: 54 | weight: 3 55 | settings: { } 56 | third_party_settings: { } 57 | type: options_select 58 | xeno_parallax: 59 | weight: 2 60 | settings: { } 61 | third_party_settings: { } 62 | type: options_select 63 | xeno_zoom: 64 | weight: 5 65 | settings: { } 66 | third_party_settings: { } 67 | type: options_select 68 | hidden: 69 | created: true 70 | status: true 71 | uid: true 72 | -------------------------------------------------------------------------------- /css/xeno-hero.css: -------------------------------------------------------------------------------- 1 | /* Paragraph specific. */ 2 | .paragraph { 3 | clear: both; 4 | } 5 | 6 | .paragraph--type--xeno-hero { 7 | display: block; 8 | position: relative; 9 | padding-top: 180px; 10 | padding-bottom: 140px; 11 | } 12 | 13 | .paragraph--type--xeno-hero ~ .paragraph--type--xeno-hero, 14 | .item .paragraph--type--xeno-hero { 15 | padding: 90px 0; 16 | } 17 | 18 | .paragraph--type--xeno-hero > .paragraph { 19 | z-index: 2; 20 | } 21 | 22 | .paragraph--type--xeno-hero:not(.paragraph--overlay--invert) h1, 23 | .paragraph--type--xeno-hero:not(.paragraph--overlay--invert) h2, 24 | .paragraph--type--xeno-hero:not(.paragraph--overlay--invert) h3, 25 | .paragraph--type--xeno-hero:not(.paragraph--overlay--invert) h4, 26 | .paragraph--type--xeno-hero:not(.paragraph--overlay--invert) h5, 27 | .paragraph--type--xeno-hero:not(.paragraph--overlay--invert) h6, 28 | .paragraph--type--xeno-hero:not(.paragraph--overlay--invert) p, 29 | .paragraph--type--xeno-hero:not(.paragraph--overlay--invert) ul, 30 | .paragraph--type--xeno-hero:not(.paragraph--overlay--invert) blockquote { 31 | color: #fff; 32 | } 33 | 34 | /* Background Image. */ 35 | .paragraph--type--xeno-hero__image { 36 | background-attachment: scroll; 37 | background-clip: border-box; 38 | background-color: #252525; 39 | background-image: none; 40 | background-origin: padding-box; 41 | background-repeat: no-repeat; 42 | background-size: 100%; 43 | height: 100%; 44 | left: 0; 45 | opacity: 1; 46 | position: absolute; 47 | top: 0 !important; 48 | transition: all 0.3s linear 0s; 49 | will-change: transform, top; 50 | z-index: 0; 51 | } 52 | 53 | .paragraph--type--xeno-hero__image:not([class*="col-"]) { 54 | width: 100%; 55 | } 56 | 57 | .paragraph--type--xeno-hero__image img { 58 | display: none; 59 | } 60 | 61 | /* Overlay. */ 62 | [data-overlay] { 63 | position: relative; 64 | } 65 | 66 | [data-overlay]::before { 67 | background: #252525 none repeat scroll 0 0; 68 | content: ""; 69 | display: block; 70 | height: 100%; 71 | left: 0; 72 | position: absolute; 73 | top: 0; 74 | width: 100%; 75 | z-index: 1; 76 | } 77 | 78 | [data-overlay] *:not(.paragraph):not(.paragraph--type--xeno-hero__image) { 79 | z-index: 2; 80 | } 81 | 82 | .paragraph--overlay--invert[data-overlay]::before { 83 | background: #fff none repeat scroll 0 0; 84 | } 85 | 86 | [data-overlay="1"]::before { 87 | opacity: 0.1; 88 | } 89 | 90 | [data-overlay="2"]::before { 91 | opacity: 0.2; 92 | } 93 | 94 | [data-overlay="3"]::before { 95 | opacity: 0.3; 96 | } 97 | 98 | [data-overlay="4"]::before { 99 | opacity: 0.4; 100 | } 101 | 102 | [data-overlay="5"]::before { 103 | opacity: 0.5; 104 | } 105 | 106 | [data-overlay="6"]::before { 107 | opacity: 0.6; 108 | } 109 | 110 | [data-overlay="7"]::before { 111 | opacity: 0.7; 112 | } 113 | 114 | [data-overlay="8"]::before { 115 | opacity: 0.8; 116 | } 117 | 118 | [data-overlay="9"]::before { 119 | opacity: 0.9; 120 | } 121 | 122 | /* Parallax. */ 123 | .paragraph--type--xeno-hero { 124 | overflow: hidden; 125 | } 126 | 127 | .paragraph--type--xeno-hero .paragraph--type--xeno-hero__image { 128 | transition: none 0s ease 0s !important; 129 | } 130 | 131 | /* Zoom. */ 132 | .paragraph--zoom .paragraph--type--xeno-hero__image { 133 | overflow: hidden; 134 | width: 100%; 135 | -webkit-animation: ken-burns 15s ease alternate infinite; 136 | -moz-animation: ken-burns 15s ease alternate infinite; 137 | -o-animation: ken-burns 15s ease alternate infinite; 138 | animation: ken-burns 15s ease alternate infinite; 139 | -webkit-transform: translate3d(0, 0, 0); 140 | } 141 | 142 | .paragraph--zoom--1 .paragraph--type--xeno-hero__image { 143 | animation-duration: 10s; 144 | } 145 | 146 | .paragraph--zoom--2 .paragraph--type--xeno-hero__image { 147 | animation-duration: 20s; 148 | } 149 | 150 | .paragraph--zoom--3 .paragraph--type--xeno-hero__image { 151 | animation-duration: 30s; 152 | } 153 | 154 | .paragraph--zoom--4 .paragraph--type--xeno-hero__image { 155 | animation-duration: 40s; 156 | } 157 | 158 | .paragraph--zoom--5 .paragraph--type--xeno-hero__image { 159 | animation-duration: 50s; 160 | } 161 | 162 | .paragraph--zoom--6 .paragraph--type--xeno-hero__image { 163 | animation-duration: 60s; 164 | } 165 | 166 | /* Zoom animation. */ 167 | @-webkit-keyframes ken-burns { 168 | 0% { 169 | transform: scale(1); 170 | } 171 | 100% { 172 | transform: scale(1.1); 173 | } 174 | } 175 | 176 | @-moz-keyframes ken-burns { 177 | 0% { 178 | transform: scale(1); 179 | } 180 | 100% { 181 | transform: scale(1.1); 182 | } 183 | } 184 | 185 | @-ms-keyframes ken-burns { 186 | 0% { 187 | transform: scale(1); 188 | } 189 | 100% { 190 | transform: scale(1.1); 191 | } 192 | } 193 | 194 | @-o-keyframes ken-burns { 195 | 0% { 196 | transform: scale(1); 197 | } 198 | 100% { 199 | transform: scale(1.1); 200 | } 201 | } 202 | 203 | @keyframes ken-burns { 204 | 0% { 205 | transform: scale(1); 206 | } 207 | 100% { 208 | transform: scale(1.1); 209 | } 210 | } 211 | -------------------------------------------------------------------------------- /templates/paragraph--xeno-hero.html.twig: -------------------------------------------------------------------------------- 1 | {# 2 | /** 3 | * @file 4 | * Default theme implementation to display the Xeno Hero Paragraphs bundle. 5 | * 6 | * Available variables: 7 | * - paragraph: Full paragraph entity. 8 | * - id: The paragraph ID. 9 | * - bundle: The type of the paragraph, for example, "image" or "text". 10 | * - authorid: The user ID of the paragraph author. 11 | * - createdtime: Formatted creation date. Preprocess functions can 12 | * reformat it by calling format_date() with the desired parameters on 13 | * $variables['paragraph']->getCreatedTime(). 14 | * - content: All paragraph items. Use {{ content }} to print them all, 15 | * or print a subset such as {{ content.field_example }}. Use 16 | * {{ content|without('field_example') }} to temporarily suppress the printing 17 | * of a given child element. 18 | * - attributes: HTML attributes for the containing element. 19 | * The attributes.class element may contain one or more of the following 20 | * classes: 21 | * - paragraphs: The current template type (also known as a "theming hook"). 22 | * - paragraphs--type-[type]: The current paragraphs type. For example, if the paragraph is an 23 | * "Image" it would result in "paragraphs--type--image". Note that the machine 24 | * name will often be in a short form of the human readable label. 25 | * - paragraphs--view-mode--[view_mode]: The View Mode of the paragraph; for example, a 26 | * preview would result in: "paragraphs--view-mode--preview", and 27 | * default: "paragraphs--view-mode--default". 28 | * - view_mode: View mode; for example, "preview" or "full". 29 | * - logged_in: Flag for authenticated user status. Will be true when the 30 | * current user is a logged-in member. 31 | * - is_admin: Flag for admin user status. Will be true when the current user 32 | * is an administrator. 33 | * 34 | * Fields: 35 | * - xeno_background_image: Image field 36 | * - xeno_content: Paragraphs field 37 | * - xeno_invert: A select list with one option. 38 | * - xeno_overlay A select list with multiple options. 39 | * - xeno_parallax A select list with one option. 40 | * 41 | * @see template_preprocess_paragraph() 42 | * 43 | * @ingroup themeable 44 | */ 45 | #} 46 | 47 | {{ attach_library('xeno_hero/xeno-hero') }} 48 | 49 | {# The template default set classes. #} 50 | {% 51 | set classes = [ 52 | 'paragraph', 53 | 'paragraph--type--' ~ paragraph.bundle|clean_class, 54 | view_mode ? 'paragraph--view-mode--' ~ view_mode|clean_class, 55 | ] 56 | %} 57 | 58 | {# Renders Overlay field. #} 59 | {# Sets data attibute value from values in database. #} 60 | {% if content.xeno_overlay|render %} 61 | {% set overlay_level = content.xeno_overlay['#items'].getString() %} 62 | {% set overlay_levels = [ 63 | '1' == overlay_level ? '1', 64 | '2' == overlay_level ? '2', 65 | '3' == overlay_level ? '3', 66 | '4' == overlay_level ? '4', 67 | '5' == overlay_level ? '5', 68 | '6' == overlay_level ? '6', 69 | '7' == overlay_level ? '7', 70 | '8' == overlay_level ? '8', 71 | '9' == overlay_level ? '9', 72 | ] 73 | %} 74 | {% endif %} 75 | 76 | {# Renders Parallax field. #} 77 | {# Sets data attibute value from values in database. #} 78 | {% if content.xeno_parallax|render %} 79 | {% set parallax_speed = content.xeno_parallax['#items'].getString() %} 80 | {% set parallax_speeds = [ 81 | '1' == parallax_speed ? '1', 82 | '2' == parallax_speed ? '2', 83 | '3' == parallax_speed ? '3', 84 | '4' == parallax_speed ? '4', 85 | '5' == parallax_speed ? '5', 86 | '6' == parallax_speed ? '6', 87 | ] 88 | %} 89 | {% endif %} 90 | 91 | {# Renders Parallax Offset field. #} 92 | {# Sets data attibute value from user input. #} 93 | {% if content.xeno_offset|render %} 94 | {% set parallax_offset = content.xeno_offset['#items'].getString() %} 95 | {% endif %} 96 | 97 | {# Renders Invert field. #} 98 | {# Sets class from values in database. #} 99 | {% if content.xeno_invert|render %} 100 | {% set invert_level = content.xeno_invert['#items'].getString() %} 101 | {% set invert_levels = [ 102 | 'invert' == invert_level ? 'paragraph--overlay--invert', 103 | ] 104 | %} 105 | {% endif %} 106 | 107 | {# Merges Invert field with classes. #} 108 | {% set invert_field = content.xeno_invert|render %} 109 | {% if invert_field %} 110 | {% set classes = classes|merge(invert_levels) %} 111 | {% endif %} 112 | 113 | {# Renders Zoom field. #} 114 | {# Sets class from values in database. #} 115 | {% if content.xeno_zoom|render %} 116 | {% set zoom_level = content.xeno_zoom['#items'].getString() %} 117 | {% set zoom_levels = [ 118 | '1' == zoom_level ? 'paragraph--zoom paragraph--zoom--1', 119 | '2' == zoom_level ? 'paragraph--zoom paragraph--zoom--2', 120 | '3' == zoom_level ? 'paragraph--zoom paragraph--zoom--3', 121 | '4' == zoom_level ? 'paragraph--zoom paragraph--zoom--4', 122 | '5' == zoom_level ? 'paragraph--zoom paragraph--zoom--5', 123 | '6' == zoom_level ? 'paragraph--zoom paragraph--zoom--6', 124 | ] 125 | %} 126 | {% endif %} 127 | 128 | {# Merges Zoom field with classes. #} 129 | {% set zoom_field = content.xeno_zoom|render %} 130 | {% if zoom_field %} 131 | {% set classes = classes|merge(zoom_levels) %} 132 | {% endif %} 133 | 134 | {# Prints div with classes, & content w/o img/invert/overlay/parallax fields. #} 135 |