* feat: first pass at CTA Tag

* fix: strip_tags before using the link

* default hover

* feat: add the type of cta

* feat: add own ltag by copying the utility class

* feat: rename property to style

* feat: add style and width

* feat: add xit test

* feat: add spec for unordered options

* chore: some css

* feat: update the cta spec to remove style and width options

* feat: move billboard related code out of widgets

* fix: mobile display ad below the comments section

* feat: cta_tag strip tags  input

* feat: update the editor docs

* feat: add help text to teh liquid guide and the editor guide

* feat: fix the css styles of the CTA

* cgore: alphabetical order

* chore: move everything on one line

---------

Co-authored-by: Mac Siri <mac@forem.com>
This commit is contained in:
Ridhwana 2023-05-12 14:30:30 +02:00 committed by GitHub
parent a1ca675e6f
commit d92e9d1af4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 217 additions and 27 deletions

View file

@ -112,6 +112,16 @@ body {
// when/if we "redesign" liquid tags.
[class*='ltag'] a {
text-decoration: none;
&:hover {
color: var(--color-hover);
}
}
a[class*='ltag'] {
text-decoration: none;
&:hover {
color: var(--color-hover);
}
}
h1,

View file

@ -0,0 +1,50 @@
@import 'config/import';
@import 'variables';
@import '_mixins';
.crayons-layout__comments-display-ad {
.crayons-sponsorship {
.c-indicator.crayons-sponsorship__indicator {
line-height: 15px;
}
padding-left: var(--content-padding-x);
padding-bottom: var(--su-6);
@media (min-width: $breakpoint-s) {
.text-styles {
padding-right: var(--su-8);
}
}
}
}
.sponsorship-dropdown {
hr {
border: 0.5px solid var(--divider);
margin: 8px;
}
}
.billboard .ltag_cta {
padding-top: var(--su-2);
padding-bottom: var(--su-2);
@media (max-width: $breakpoint-s) {
display: block;
}
}
// refers to the sidebar billboards where we use cards
.crayons-card.billboard .ltag_cta {
display: block;
}
// these are inline CTA's
//refers to the below the comments billboard on the article page
//refers to the feed/stories where we use story
.crayons-layout__comments-display-ad .crayons-card.billboard .ltag_cta,
.crayons-story.billboard .ltag_cta {
padding-right: var(--su-7);
padding-left: var(--su-7);
}

View file

@ -0,0 +1,49 @@
.ltag_cta {
--border-width: 1px;
padding: var(--su-2) var(--su-4);
border: var(--border-width) solid;
border-color: var(--border);
text-decoration: none;
border-radius: var(--radius);
font: inherit;
background-color: var(--bg);
color: var(--color);
outline: 0;
text-align: center;
display: inline-flex;
position: relative;
overflow-wrap: normal;
&:hover,
.js-focus-visible &.focus-visible:focus {
background-color: var(--bg-hover);
border-color: var(--border-hover);
color: var(--color-hover);
z-index: var(--z-elevate);
text-decoration: underline;
}
.js-focus-visible &.focus-visible:focus {
box-shadow: var(--focus-ring);
}
}
.ltag_cta {
--bg: var(--cta-bg);
--bg-hover: var(--cta-bg-hover);
--color: var(--cta-color);
--color-hover: var(--cta-color-hover);
--border: var(--cta-border);
--border-hover: var(--cta-border-hover);
&--branded {
--bg: var(--cta-branded-bg);
--bg-hover: var(--cta-branded-bg-hover);
--color: var(--cta-branded-color);
--color-hover: var(--cta-branded-color-hover);
--border: var(--cta-branded-border);
--border-hover: var(--cta-branded-border-hover);
font-weight: var(--fw-medium);
}
}

View file

@ -1,4 +1,5 @@
@import 'CommentTag';
@import 'CtaTag';
@import 'GistTag';
@import 'GithubReadmeTag';
@import 'GithubTag';

View file

@ -3,6 +3,7 @@
@import 'scaffolds';
@import 'articles';
@import 'article-show';
@import 'billboards';
@import 'shared';
@import 'dashboard';
@import 'settings';

View file

@ -351,24 +351,3 @@
}
}
}
.crayons-layout__comments-display-ad {
.crayons-sponsorship {
.c-indicator.crayons-sponsorship__indicator {
line-height: 15px;
}
padding-left: var(--content-padding-x);
padding-bottom: var(--su-6);
.text-styles {
padding-right: var(--su-8);
}
}
}
.sponsorship-dropdown {
hr {
border: 0.5px solid var(--divider);
margin: 8px;
}
}

View file

@ -0,0 +1,36 @@
class CtaTag < Liquid::Block
include ActionView::Helpers::SanitizeHelper
PARTIAL = "liquids/cta".freeze
# at some point we may want to pass in options to dictate which type of CTA the user wants to use,
# i.e. secondary, primary, branded. This sets the scene for it without actually providing that option now.
TYPE_OPTIONS = %w[branded].freeze
DESCRIPTION_LENGTH = 128
def initialize(_tag_name, options, _parse_context)
super
@link = strip_tags(options.strip)
end
def render(_context)
content = Nokogiri::HTML.parse(super)
ApplicationController.render(
partial: PARTIAL,
locals: {
link: @link,
description: sanitized_description(content),
type: TYPE_OPTIONS.first
},
)
end
private
def sanitized_description(content)
stripped_description = strip_tags(content.xpath("//html/body").inner_html).delete("\n").strip
stripped_description.truncate(DESCRIPTION_LENGTH)
end
end
Liquid::Template.register_tag("cta", CtaTag)

View file

@ -0,0 +1 @@
<a href="<%= link %>" class="ltag_cta ltag_cta--<%= type %>" role="button"><%= description %></a>

View file

@ -45,11 +45,15 @@
<h3>Supported Non-URL Embeds</h3>
<h4>Call To Action (CTA)</h4>
<p><pre>{% cta link %} description {% endcta %}</pre></p>
<p>Provide a <em>link</em> that a user will be redirected to. The <em>description</em> will contain the label/description for the call to action.</p>
<h4>Details</h4>
<p>You can embed a <code>details</code> HTML element by using details, spoiler, or collapsible. The <em>summary</em> will be what the dropdown title displays. The <em>content</em> will be the text hidden behind the dropdown. This is great for when you want to hide text (i.e. answers to questions) behind a user action/intent (i.e. a click).</p>
<p><code>{% details summary %} content {% enddetails %}</code></p>
<p><code>{% spoiler summary %} content {% endspoiler %}</code></p>
<p><code>{% collapsible summary %} content {% endcollapsible %}</code></p>
<p><pre>{% details summary %} content {% enddetails %}</pre></p>
<p><pre>{% spoiler summary %} content {% endspoiler %}</pre></p>
<p><pre>{% collapsible summary %} content {% endcollapsible %}</pre></p>
<h4>KaTex</h4>
<p>Place your mathematical expression within a KaTeX liquid block, as follows:</p>
@ -65,7 +69,7 @@
<h4><%= community_name %> User Subscriptions</h4>
<p class="fs-s fw-bold">This embed can only be created within posts by Admins.</p>
<p>You can add call-to-action text that will show above the subscribe button:</p>
<code>{% user_subscription If you'd like to receive future updates, subscribe below! %}</code>
<pre>{% user_subscription If you'd like to receive future updates, subscribe below! %}</pre>
<p class="fs-s">
If a reader is signed out, the button will prompt them to sign in first
to subscribe. If the reader is signed in, the button will prompt them

View file

@ -45,6 +45,10 @@
<h3>Supported Non-URL Embeds</h3>
<h4>Call To Action (CTA)</h4>
<p><pre>{% cta link %} description {% endcta %}</pre></p>
<p>Provide a <em>link</em> that a user will be redirected to. The <em>description</em> will contain the label/description for the call to action.</p>
<h4>Details</h4>
<p>You can embed a <code>details</code> HTML element by using details, spoiler, or collapsible. The <em>summary</em> will be what the dropdown title displays. The <em>content</em> will be the text hidden behind the dropdown. This is great for when you want to hide text (i.e. answers to questions) behind a user action/intent (i.e. a click).</p>
<p><code>{% details summary %} content {% enddetails %}</code></p>

View file

@ -1,5 +1,9 @@
<% @user_approved_liquid_tags = Users::ApprovedLiquidTags.call(@user) %>
<h4>Call To Action (CTA)</h4>
<p><pre>{% cta link %} description {% endcta %}</pre></p>
<p>Provide a <em>link</em> that a user will be redirected to. The <em>description</em> will contain the label/description for the call to action.</p>
<h4>Details</h4>
<p>You can embed a <code>details</code> HTML element by using details, spoiler, or collapsible. The <em>summary</em> will be what the dropdown title displays. The <em>content</em> will be the text hidden behind the dropdown. This is great for when you want to hide text (i.e. answers to questions) behind a user action/intent (i.e. a click).</p>
<pre>

View file

@ -1,5 +1,9 @@
<% @user_approved_liquid_tags = Users::ApprovedLiquidTags.call(@user) %>
<h4>Call To Action (CTA)</h4>
<p><pre>{% cta link %} description {% endcta %}</pre></p>
<p>Provide a <em>link</em> that a user will be redirected to. The <em>description</em> will contain the label/description for the call to action.</p>
<h4>Details</h4>
<p>You can embed a <code>details</code> HTML element by using details, spoiler, or collapsible. The <em>summary</em> will be what the dropdown title displays. The <em>content</em> will be the text hidden behind the dropdown. This is great for when you want to hide text (i.e. answers to questions) behind a user action/intent (i.e. a click).</p>
<pre>

View file

@ -1,5 +1,5 @@
<% if display_ad.placement_area.start_with?("feed_") %>
<div class="crayons-story crayons-story__display-ad"
<div class="crayons-story crayons-story__display-ad billboard"
data-display-unit data-id="<%= display_ad.id %>"
data-category-click="<%= DisplayAdEvent::CATEGORY_CLICK %>"
data-category-impression="<%= DisplayAdEvent::CATEGORY_IMPRESSION %>"
@ -17,7 +17,7 @@
</div>
</div>
<% else %>
<div class="crayons-card crayons-card--secondary crayons-sponsorship"
<div class="crayons-card crayons-card--secondary crayons-sponsorship billboard"
data-display-unit data-id="<%= display_ad.id %>"
data-category-click="<%= DisplayAdEvent::CATEGORY_CLICK %>"
data-category-impression="<%= DisplayAdEvent::CATEGORY_IMPRESSION %>"

View file

@ -0,0 +1,47 @@
require "rails_helper"
RSpec.describe CtaTag, type: :liquid_tag do
describe "#render" do
let(:link) { "https://dev.to/" }
let(:description) { "DEV Community" }
def generate_details_liquid(options, description)
Liquid::Template.register_tag("cta", described_class)
Liquid::Template.parse("{% cta #{options} %} #{description} {% endcta %}")
end
it "contains the correct static attributes" do
rendered = generate_details_liquid(link, description).render
expect(rendered).to include("class=\"ltag_cta ltag_cta--branded")
expect(rendered).to include("role=\"button")
end
it "generates the correct href attribute" do
rendered = generate_details_liquid(link, description).render
expect(rendered).to include("href=\"#{link}")
end
it "contains the correct description" do
rendered = generate_details_liquid(link, description).render
expect(rendered).to include(description)
end
it "limits the description to 128 characters" do
long_description = "We do not allow for more than hundred and twenty eight characters in the description of " \
"the CTA. This is the same as what we allow for article titles."
rendered = generate_details_liquid(link, long_description).render
expect(rendered).to include("We do not allow for more than hundred and twenty eight characters in the " \
"description of the CTA. This is the same as what we ...")
expect(rendered).not_to include("article titles.")
end
it "strips all tags from the description" do
rendered = generate_details_liquid(link, "<div class='crayons'>DEV Community</div>").render
expect(rendered).to include("DEV Community")
expect(rendered).not_to include("class='crayons'")
expect(rendered).not_to include("<div")
expect(rendered).not_to include("</div>")
end
end
end