$elementor->widgets_manager->register_widget_type( new Widgets\TextBlock() );
$elementor->widgets_manager->register_widget_type( new Widgets\Heading() );
$elementor->widgets_manager->register_widget_type( new Widgets\Timeline() );
+ $elementor->widgets_manager->register_widget_type( new Widgets\FeatureBlock() );
}
protected function _customise_sections() {
]
);
+ $element->add_control(
+ 'stacking_margins',
+ [
+ 'label' => __('Disable margins when stacking columns?', 'cube'),
+ 'type' => Controls_Manager::SWITCHER,
+ 'default' => '',
+ 'return_value' => 'no-column-stacking-gap',
+ 'prefix_class' => '',
+ ]
+ );
+
}, 10, 2 );
--- /dev/null
+<?php
+
+namespace Cube\Elementor\Widgets;
+
+use Elementor\Widget_Base;
+use Elementor\Controls_Manager;
+use Elementor\Utils;
+
+
+/**
+ * Class Subtitle
+ * @package Cube\Elementor\Widgets
+ */
+class FeatureBlock extends Widget_Base
+{
+
+ // Widget name / ID
+ public function get_name() {
+ return 'cube-feature-block';
+ }
+
+ // Elementor widget title
+ public function get_title() {
+ return __('Feature Block', 'cube');
+ }
+
+ // Elementor interface icon
+ public function get_icon() {
+ return 'eicon-posts-grid';
+ }
+
+ // Where to display the widget in the Elementor interface
+ public function get_categories() {
+ return ['theme-elements'];
+ }
+
+ /**
+ * List of scripts the widget depends on.
+ * Used to set scripts dependencies required to run the widget.
+ *
+ * @since 1.0.0
+ * @access public
+ * @return array Widget scripts dependencies.
+ */
+ public function get_script_depends() {
+ return [];
+ }
+
+ /**
+ * Register the widget controls.
+ * Adds different input fields to allow the user to change and customize the widget settings.
+ *
+ * @since 1.0.0
+ * @access protected
+ */
+ protected function _register_controls() {
+
+ $this->start_controls_section(
+ 'section_content',
+ [
+ 'label' => __('Content', 'cube'),
+ ]
+ );
+
+ $this->add_control(
+ 'image',
+ [
+ 'label' => __( 'Image', 'elementor' ),
+ 'type' => Controls_Manager::MEDIA,
+ 'default' => [
+ 'url' => Utils::get_placeholder_image_src(),
+ ],
+ ]
+ );
+
+ $this->add_control(
+ 'image_bottom_margin',
+ [
+ 'label' => __( 'Image Margin (override)', 'cube' ),
+ 'type' => Controls_Manager::TEXT,
+ 'default' => '',
+ 'selectors' => [
+ '{{WRAPPER}} .feature-block-image' => 'margin-bottom: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_control(
+ 'title',
+ [
+ 'label' => __('Title', 'elementor'),
+ 'type' => Controls_Manager::TEXTAREA,
+ 'placeholder' => __('Enter your title', 'elementor'),
+ 'default' => '',
+ ]
+ );
+
+ $this->add_control(
+ 'description',
+ [
+ 'label' => __('Description', 'cube'),
+ 'type' => Controls_Manager::TEXTAREA,
+ 'default' => '',
+ ]
+ );
+
+ $this->add_control(
+ 'bg_color',
+ [
+ 'label' => __( 'Background Colour', 'cube' ),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '',
+ 'selectors' => [
+ '{{WRAPPER}} .feature-block-content' => 'background-color: {{VALUE}};',
+ ],
+ ]
+ );
+
+
+ $this->add_control(
+ 'text_color',
+ [
+ 'label' => __( 'Text Colour', 'cube' ),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '',
+ 'selectors' => [
+ '{{WRAPPER}} .feature-block' => 'color: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_control(
+ 'circle',
+ [
+ 'label' => __('Circular Background', 'cube'),
+ 'type' => Controls_Manager::SWITCHER,
+ 'default' => '',
+ 'return_value' => 'circle',
+ 'prefix_class' => 'feature-block-'
+ ]
+ );
+
+ $this->end_controls_section();
+
+ }
+
+ /**
+ * Render the widget output on the frontend.
+ * Written in PHP and used to generate the final HTML.
+ *
+ * @since 1.0.0
+ * @access protected
+ */
+ protected function render() {
+
+ $image = $this->get_settings('image');
+ $title = $this->get_settings('title');
+ $description = $this->get_settings('description');
+
+ // CSS Classes for elements
+ $this->add_render_attribute('title', 'class', ['feature-block-title']);
+ $this->add_render_attribute('description', 'class', ['feature-block-description']);
+
+ // Rendered content
+ echo '<div class="feature-block">';
+ echo '<div class="feature-block-wrapper">';
+ echo '<div class="feature-block-content">';
+
+ if (!empty($image['id'])) {
+ echo wp_get_attachment_image($image['id'], 'medium', false, ['class' => 'feature-block-image']);
+ }
+
+ if (!empty($title)) {
+ echo "<h3 {$this->get_render_attribute_string('title')}>$title</h3>";
+ }
+
+ if (!empty($description)) {
+ echo "<div {$this->get_render_attribute_string('description')}>". nl2br($description) ."</div>";
+ }
+
+ echo '</div>'; // .feature-block-content
+ echo '</div>'; // .feature-block-wrapper
+ echo '</div>'; // .feature-block
+ }
+
+}
use Elementor\Widget_Base;
use Elementor\Controls_Manager;
-use Elementor\Scheme_Color;
/**
<div class="hero-block-content">
<div class="hero-block-content-inner">
- <h1 class="hero-block-title"><?= $title ?><div class="hero-block-body"><?= $body ?></div></h1>
+ <h1 class="hero-block-title"><?= \App\prevent_orphans($title) ?><div class="hero-block-body"><?= $body ?></div></h1>
</div>
</div>
use Elementor\Widget_Base;
use Elementor\Controls_Manager;
-use Elementor\Scheme_Color;
class TextBlock extends Widget_Base {
]
);
-
- $this->add_control(
- 'subtitle',
- [
- 'label' => __( 'Subtitle', 'cube' ),
- 'type' => Controls_Manager::TEXT,
- 'default' => '',
- ]
- );
-
$this->add_control(
'title',
[
*/
protected function render() {
- $subtitle = $this->get_settings('subtitle');
$title = $this->get_settings('title');
$title_size = $this->get_settings('title_size');
$body = $this->parse_text_editor($this->get_settings('body'));
}
// Inline Editing settings
- $this->add_inline_editing_attributes('subtitle', 'none');
$this->add_inline_editing_attributes('title', 'none');
$this->add_inline_editing_attributes('body', 'advanced');
$this->add_inline_editing_attributes('cta_text', 'none');
// CSS Classes for elements
- $this->add_render_attribute('subtitle', 'class', ['text-block-subtitle']);
$this->add_render_attribute('title', 'class', ['text-block-title']);
$this->add_render_attribute('body', 'class', ['text-block-body']);
$this->add_render_attribute('cta_text', 'class', ['text-block-cta arrow-link']);
// Rendered content
echo '<div class="text-block">';
- if (!empty($subtitle)) echo "<h3 {$this->get_render_attribute_string('subtitle')}>$subtitle</h3>";
if (!empty($title)) echo "<h2 {$this->get_render_attribute_string('title')}>$title</h2>";
if (!empty($body)) echo "<div {$this->get_render_attribute_string('body')}>$body</div>";
if (!empty($cta_text)) {
protected function _content_template() {
?>
<#
- view.addRenderAttribute( 'subtitle', 'class', ['text-block-subtitle']);
view.addRenderAttribute( 'title', 'class', ['text-block-title']);
view.addRenderAttribute( 'body', 'class', ['text-block-body']);
view.addRenderAttribute( 'cta_text', 'class', ['text-block-cta arrow-link']);
view.addRenderAttribute('title', 'class', ['text-block-title-size-' + settings.title_size]);
}
- view.addInlineEditingAttributes( 'subtitle', 'none' );
view.addInlineEditingAttributes( 'title', 'none' );
view.addInlineEditingAttributes( 'body', 'advanced' );
view.addInlineEditingAttributes( 'cta_text', 'none' );
#>
<div class="text-block">
- <# if ('' !== settings.subtitle) { #>
- <h3 {{{ view.getRenderAttributeString( 'subtitle' ) }}}>{{{ settings.subtitle }}}</h3>
- <# } #>
-
<# if ('' !== settings.title) { #>
<h2 {{{ view.getRenderAttributeString( 'title' ) }}}>{{{ settings.title }}}</h2>
<# } #>
isset($display) || $display = apply_filters('sage/display_sidebar', false);
return $display;
}
+
+
+/**
+ * Prevent a string from having orphans by replacing the
+ * last space between words with a non-breaking space
+ * @param string $text Text to be de-orphaned
+ * @return string
+ */
+function prevent_orphans($text)
+{
+ $search = ' '; // Search for spaces
+ $replace = ' '; // Replace with non-breaking space
+
+ $text = trim($text); // Trim off any excess spaces at beginning and end
+ $pos = strrpos($text, ' '); // Find the last occurrence in the string
+
+ if($pos !== false) {
+ $text = substr_replace($text, $replace, $pos, strlen($search));
+ }
+
+ return $text;
+}
html
box-sizing: border-box
height: 100%
- font-size: $font-size-base // This value won't be converted to REMs due to exception in font-size() mixin
+ font-size: $font-size.base // This value won't be converted to REMs due to exception in font-size() mixin
+below(1250px)
font-size: 15px
+below(1024px)
u = unit(value)
if (u is 'px')
- return unit(value / $font-size-base, 'rem')
+ return unit(value / $font-size.base, 'rem')
else
return value
// Fonts
$font = 'Muli', sans-serif
-// TODO: replace any $font-size-xxx variable references with $font-size array below
// Font sizing
-$font-size-base = 16px // Size of 1rem
-
-$font-size-extra-large = 81px // h1
-$font-size-large = 54px // h2
-$font-size-medium = 36px // h3
-$font-size-small = 24px // h4
-$font-size-extra-small = 12px //
-
+// See utilities.styl for font-size helper classes
+// (can't be done here because we need the mixins to be included first)
$font-size = {
- 'sm': 12px,
- 'base': 16px,
- 'lg': 24px, // h4
- 'xl': 36px, // h3
- '2xl': 54px, // h2
- '3xl': 81px, // h1
+ small: 12px,
+ base: 16px, // Size of 1rem
+ medium: 24px, // h4
+ large: 36px, // h3
+ extra-large: 54px, // h2
+ huge: 81px, // h1
}
-// See utilities.styl for font-size helpers (can't be done here because we need the mixins to be included first)
// Breakpoints in Rupture (https://github.com/jescalan/rupture)
rupture.scale = 0 400px 768px 1024px
padding: 2em 5em
text-align: center
font-smoothing()
- font-size: 12px
+ font-size: $font-size.small fixed // Don't use REMs
font-weight: 800
text-transform: uppercase
transition: all 0.3s ease-out
color: $placeholder-color
input, textarea, select
- font-size: $font-size-base
+ font-size: $font-size.base
font-family: $font
outline: none
background-color: transparent
h1, h2
font-family: $font
- font-size: $font-size-large
+ font-size: $font-size.extra-large
line-height: 1.1
margin-bottom: 0.4em
font-weight: 500
-h3
+h3, h4
line-height: 1.4
font-weight: 500
+h3
+ font-size: $font-size.large
+
+h4
+ font-size: $font-size.medium
+
.elementor-widget-heading
.elementor-heading-title
color: $colors.headings
font-family: $font
- font-size: $font-size-large
+ font-size: $font-size.extra-large
white-space: pre-wrap
line-height: 1.4
+below('large')
- font-size: $font-size-medium
+ font-size: $font-size.large
//&:after
// content: ''
// Default styling for text blocks
-// Applied to .elementor-widget-container so Elemntor editor settings can override this setting
-.elementor-widget-text-editor .elementor-widget-container
- horizontal-spacing(10vw)
- padding-top: 40px
- padding-bottom: 40px
-
- //p
- // max-width: 400px
- // font-weight: 300
- // line-height: 1.8
+.elementor-widget-text-editor
+
+ // Applied to .elementor-widget-container so Elementor editor settings can override this setting
+ .elementor-widget-container
+ //horizontal-spacing(10vw)
+ //padding-top: 40px
+ //padding-bottom: 40px
+ center(960px)
+
+ // Extra bit of space when there's a heading + paragraph
+ h1 + p, h2 + p , h3 + p, h4 + p
+ margin-top: 0.5em
+
+ a
+ color: $colors.orange
+
+ &:hover
+ border-bottom: 1px dotted
$breakpoint-footer-cols-2 = 980px // When to break to 2 col view
$breakpoint-footer-medium = 800px // Layout with logo + address on same line / other items stacked below
-$breakpoint-footer-cols-1 = 710px // When to break to 1 col view
+$breakpoint-footer-cols-1 = 500px // When to break to 1 col view
.footer
-.elementor-section.elementor-section-full_width
- //--- Columns responsiveness
- // Full width sections have columns stacked but no margin is placed between them
- // This is to accommodate the flexible background image blocks
-
- // TODO: consider adding a "no gap" option to the section when wrapping? Then it can be applied to full width or boxed sections...
-
-
- +below($breakpoint-columns)
- .elementor-column
- width: 100% !important
-
-
-.elementor-section.elementor-section-boxed
-
+.elementor-section
//--- Columns responsiveness - stack all standard columns below breakpoint
+below($breakpoint-columns)
.elementor-column
&:not(:last-of-type)
margin-bottom: 7.5vw
+ // There's a toggle in the editor so we can disable
+ // this margin between columns when stacking vertically
+ &.no-column-stacking-gap
+ .elementor-column
+ +below($breakpoint-columns)
+ margin-bottom: 0
+
//--- Default section layout
- &.layout-default
+ &.layout-default.elementor-section-boxed
> .elementor-container
center($content-max-width * 0.8) // 1920px * 0.8 = 1536px
horizontal-spacing(5vw)
margin: 12px !important
a
- color: $colors.secondary
+ color: $colors.orange
border-bottom: 1px dotted
--- /dev/null
+$breakpoint-circles = 1200px // Below this, circles aren't shown because content can't fit properly
+
+// Ensure full height on element so the content always covers the full area
+.elementor-widget-cube-feature-block,
+.elementor-widget-container,
+.feature-block,
+.feature-block-wrapper,
+.feature-block-content
+ height: 100%
+
+
+.feature-block
+
+ // When the content has a circle around it, we need to add
+ // padding to this outer div in order to give the circle some margin
+ .feature-block-circle &
+ +above($breakpoint-circles)
+ vertical-spacing(3vw)
+ horizontal-spacing(7.5vw)
+ display: flex
+ align-items: center
+ justify-content: center
+
+ &-wrapper
+
+ // Make the wrapper square so it will hold a perfect circle
+ // In this mode, content is taken out of the flow with absolute
+ // positioning, allowing proportional padding to be used to make
+ // a responsive square...
+ .feature-block-circle &
+ +above($breakpoint-circles)
+ flex: 1 1 auto
+ height: auto
+ padding-bottom: 100%
+ position: relative
+
+
+ &-content
+ constrain(padding, 7.5vw)
+ display: flex
+ flex-direction: column
+ align-items: center
+ justify-content: center
+ text-align: center
+ border-radius: 4px
+
+ // Make a circle within the square wrapper
+ .feature-block-circle &
+ +above($breakpoint-circles)
+ constrain(padding, 3vw) // Less padding due to circle
+ border-radius: 50%
+ position: absolute
+ top: 0
+ left: 0
+ width: 100%
+ height: 100%
+
+ &-image
+ margin-bottom: 2em
+
+ &-title
+ font-size: $font-size.medium
+ font-weight: 300
+ line-height: 1.2
+ white-space: pre-line
+
+ &-description
+ font-weight: 300
+ line-height: 1.8
+ margin-top: 0.5em
+
.heading
position: relative
horizontal-spacing(7.5vw)
- font-size: $font-size-extra-large // Size for title + used for positioning subtitle
+ //font-size: $font-size.huge // Size for title + used for positioning subtitle
+ constrain(font-size, 4.2vw)
+
+ +below(1200px)
+ font-size: $font-size.extra-large
&-subtitle-wrapper
position: absolute
border-left: 2px solid
padding-left: 0.25em
text-transform: uppercase
- font-size: 12px fixed
+ font-size: $font-size.small fixed
color: $colors.orange
+below(1000px)
&-title
- font-size: $font-size-extra-large
+ font-size: $font-size.huge
font-weight: 700
white-space: pre-line
margin: 0
line-height: 1
text-align: center
- +below(500px)
+ +below(720px)
white-space: normal
font-size: 60px
.text-block
- &-subtitle
- display: inline-block
- font-size: $font-size-base
- font-weight: 600
- text-transform: uppercase
- border: 2px solid
- padding: 0.15em 0.5em
- margin-bottom: 1em
-
&-title
font-smoothing()
white-space: pre-line
- font-size: $font-size-large
+ font-size: $font-size.extra-large
font-weight: 300
+below(1600px)
white-space: normal // Avoid strange gaps caused by pre-line breaks wrapping
font-size: 4.25vw // Using vw units so headings scale instead of wrapping further
+below(795px) // Cap font size to medium once the vw size matches medium size
- font-size: $font-size-medium // Note: also affected by the base HTML font size since it is converted rems
+ font-size: $font-size.large // Note: also affected by the base HTML font size since it is converted rems
//+below(large)
- // font-size: $font-size-medium
+ // font-size: $font-size.large
//+below(medium)
// font-size: 35px
&-size-medium
- font-size: $font-size-medium
+ font-size: $font-size.large
// No bottom margin if it's the last element (ie. no body below)
&:last-child
font-weight: 400
margin-top: r(40px)
+ // If the body is the first child, there's no title
+ // so we don't want the top margin...
+ &:first-child
+ margin-top: 0
+
h3
font-size: 30px
font-weight: 500
&-cta
font-smoothing()
- font-size: 12px fixed // Won't be converted to rems
+ font-size: $font-size.small fixed // Won't be converted to rems
font-weight: 800
text-transform: uppercase
display: inline-block
display: block
margin-bottom: 1.5em
&.active
- font-size: $font-size-small
+ font-size: $font-size.medium
color: $colors.orange
.timeline
&-year
margin-bottom: 0.8888em
&-title
- font-size: $font-size-medium
+ font-size: $font-size.large
margin-bottom: 1.333em
&-img
margin-bottom: 48px
p
margin-bottom: 3em
h4
- font-size: $font-size-small
+ font-size: $font-size.medium
font-weight: lighter
margin-bottom: 1em
margin-top: 2em
h3
- font-size: $font-size-medium
+ font-size: $font-size.large
font-weight: lighter
margin-bottom 1.33em
ul
left: -1.6em
top: 12px
&:last-of-type
- margin-bottom: 0
\ No newline at end of file
+ margin-bottom: 0