Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convert manual-multiple template to svelte #338

Merged
merged 19 commits into from
Jan 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion src/lib/Previews.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import { replaceGAMVariables } from '$lib/gam';
import { onMount } from 'svelte';
import type { Message } from './messenger';
import { tones } from './types/tones';

export let template: string;
export let html: string;
Expand Down Expand Up @@ -90,7 +91,16 @@
<ul>
{#each Object.keys(props) as prop}
<li>
{prop}: <input type="text" bind:value={props[prop]} />
{#if prop === 'Tone'}
{prop}:
<select bind:value={props[prop]}>
{#each tones as tone}
<option value={tone}>{tone}</option>
{/each}
</select>
{:else}
{prop}: <input type="text" bind:value={props[prop]} />
{/if}
</li>
{/each}
</ul>
Expand Down
7 changes: 5 additions & 2 deletions src/lib/gam.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
const CLICK_MACRO = '%%CLICK_URL_UNESC%%';
const CACHE_BUST = '%%CACHEBUSTER%%';

type GAMVariable<T extends string = string> = `[%${T}%]`;
type GAMVariable<T extends string = string> = T;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is necessary so that the template parameters can be used for logic, as typescript complains about stuff like thsi otherwise.

export let Var: GamVariable;

// ts complains because 'true' can never satisfy `[%${T}%]`
if (Var === 'true') {
//
}


const gamVar = <T extends string>(s: T): GAMVariable<T> => `[%${s}%]`;
const gamVar = <T extends string>(s: T): `[%${GAMVariable<T>}%]` => `[%${s}%]`;

const replaceGAMVariables = (
input: string,
Expand All @@ -30,6 +30,8 @@ const addTrackingPixel = (url: string) => {
const isValidReplacedVariable = (s: GAMVariable): boolean =>
s.length > 0 && !s.startsWith('[%') && !s.endsWith('%]');

const clickMacro = (url: string): string => `${CLICK_MACRO}${url}`;

export type { GAMVariable };
export {
CACHE_BUST,
Expand All @@ -38,4 +40,5 @@ export {
gamVar,
isValidReplacedVariable,
replaceGAMVariables,
clickMacro,
};
2 changes: 1 addition & 1 deletion src/lib/svelte.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ type Props = Record<string, GAMVariable>;

const REGEX = {
script: /<script[\s\S]*?>[\s\S]+?<\/script>/g,
props: /export let (.+?): GAMVariable;/g,
props: /export let (.+?): GAMVariable(<[\s\S]+>)?;/g,
};

const getProps = (path: string): Props => {
Expand Down
24 changes: 24 additions & 0 deletions src/lib/types/tones.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
const tones = [
'brand',
'brand-new',
'job',
'live',
'travel',
'money',
'book',
'weekly',
'members',
'patron',
'lifestyle',
'climate',
'climate2',
'support',
'subscription',
'subs-rebrand',
];

type Tone = typeof tones[number];

export type { Tone };

export { tones };
113 changes: 62 additions & 51 deletions src/templates/components/ManualCard.svelte
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<script context="module" lang="ts">
import { CLICK_MACRO } from '$lib/gam';
import type { GAMVariable } from '$lib/gam';
import { clickMacro } from '$lib/gam';
import type { Tone } from '$lib/types/tones';
</script>

<script lang="ts">
Expand All @@ -9,42 +9,33 @@
import '$templates/components/fonts/Sans.css';
import ArrowRight from './icons/ArrowRight.svelte';

export let TotalCardNumber: number;
export let EventTitle: GAMVariable;
export let EventDateTime: GAMVariable;
export let EventImage: GAMVariable;
export let EventUrl: GAMVariable;
export let direction = 'row';

let [boldTitle, regularTitle] = EventTitle.split(':');
if (regularTitle) {
boldTitle += ':';
} else {
regularTitle = '';
}
export let image: string;
export let url: string;
export let linkText: string;
export let tone: Tone;
export let isProminent = false;
</script>

<a
class="card split-into-{TotalCardNumber}"
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The split into stuff didn't actually work, seems better to filter the events that actually have text in them https://github.com/guardian/commercial-templates/pull/338/files#diff-e5ba83f56a29bdc63ad7241c5b53c92078a77913d1af94896e4a83c974231bf6R69

href={EventUrl}
style={`--direction: ${direction}`}
>
<a class="card" class:is-prominent={isProminent} href={clickMacro(url)}>
<div class="media">
<picture>
<img src={EventImage} alt="" />
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the future, it would be good to offer alt text as a GAM variable, for when the image doesn't load

<img src={image} alt="" />
</picture>
</div>

<div class="text">
<h2><b>{boldTitle}</b>{regularTitle}</h2>
<p>{EventDateTime}</p>
<h2><slot name="title" /></h2>
<p><slot name="text" /></p>
{#if linkText}
<span class="button" data-tone={tone}>
{linkText}
<ArrowRight width={24} />
</span>
{/if}
</div>
<a class="button" href={`${CLICK_MACRO}${EventUrl}`} target="_top">
Book tickets
<ArrowRight width={24} />
</a>
</a>

<style>
<style lang="scss">
a {
color: #000000;
text-decoration: none;
Expand All @@ -54,11 +45,7 @@
padding: 12px 10px;
display: block;
margin: 0px;
width: 50%;
}

a.card:nth-child(n + 3) {
display: none;
flex: 1;
}

a.card:not(:first-of-type)::before {
Expand All @@ -72,7 +59,6 @@
}

.media {
background-color: gray;
margin: 0 0 10px 0;
}

Expand All @@ -83,7 +69,9 @@
picture,
img {
display: block;
width: 100%;
width: auto;
max-width: 100%;
max-height: 150px;
}

h2 {
Expand All @@ -104,13 +92,13 @@
margin: 3px 0px;
}

a.button {
.button {
font-size: 12px;
line-height: 0;
font-weight: 700;
font-family: 'GuardianTextSans', 'Helvetica Neue', Helvetica, Arial,
'Lucida Grande', sans-serif;
background: #c83877;
background: var(--bg);
color: #ffffff;
text-decoration: none;
border-radius: 10rem;
Expand All @@ -121,26 +109,20 @@
align-items: center;
}

@media (max-width: 739px) {
a.card:nth-child(n + 3) {
display: none;
}
}

@media (min-width: 740px) {
a.card:nth-child(n) {
a.card {
padding: 12px 10px;
display: block;
margin: 0px;
}

a.split-into-2 {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is handled by flexbox

width: 50%;
}

a.split-into-3 {
width: 33%;
}

a.split-into-4 {
width: 25%;
}

a.button {
.button {
margin-top: 6px;
margin-bottom: 10px;
}
Expand All @@ -152,6 +134,35 @@
p {
margin: 10px 0px;
}

.is-prominent.card:nth-child(1) {
display: flex;
flex-direction: row;
align-items: stretch;

.media {
width: calc(66.67% - 10px);
margin-right: 10px;

picture,
img {
max-height: 100%;
}
}

.text {
flex: 1;
padding: 6px 10px 6px 0;
display: flex;
flex-direction: column;
align-items: flex-start;
}

.button {
margin-top: auto;
margin-bottom: 4px;
}
}
}

@media (min-width: 1140px) {
Expand Down
117 changes: 117 additions & 0 deletions src/templates/components/ManualHeader.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
<script context="module" lang="ts">
import { clickMacro } from '$lib/gam';
</script>

<script lang="ts">
import ArrowRight from './icons/ArrowRight.svelte';
import '$templates/components/fonts/Headline.css';
import '$templates/components/fonts/SansBold.css';
import '$templates/components/colours/tones.css';
import type { Tone } from '$lib/types/tones';
import ToneLogo from './ToneLogo.svelte';

export let buttonUrl: string;
export let buttonText: string;
export let tone: Tone;
</script>

<header data-tone={tone}>
<div class="logo">
<ToneLogo {tone} />
</div>

<div class="banner-description-container">
<span class="banner-description">
<slot />
</span>
</div>

<div class="button-container">
<a class="button" href={clickMacro(buttonUrl)} target="_top">
{buttonText}
<ArrowRight width={30} />
</a>
</div>
</header>

<style lang="scss">
header {
background-color: var(--bg);
color: black;
padding: 6px 20px;
flex-shrink: 0;
display: flex;
align-items: center;
justify-content: space-between;
}

.logo {
align-self: flex-start;
}

a {
color: inherit;
text-decoration: none;
}

.banner-description {
font-size: 16px;
line-height: 22px;
font-family: 'GH Guardian Headline', 'Georgia', serif;
font-weight: 500;
color: #000000;
background: #ffffff;
box-decoration-break: clone;
-webkit-box-decoration-break: clone;
padding: 2px 5px 2px 2px;

@media (max-width: 1140px) {
display: none;
}
}

div.banner-description-container {
margin-top: 20px;
margin-bottom: 20px;
}

.button-container {
display: flex;
flex-direction: row;
}

a.button {
font-size: 13px;
font-weight: 700;
font-family: 'GuardianTextSans', 'Helvetica Neue', Helvetica, Arial,
'Lucida Grande', sans-serif;
background: var(--header-btn-bg, #ffffff);
color: #000000;
text-decoration: none;
border-radius: 10rem;
padding: 3px;
padding-left: 1rem;
display: inline-flex;
justify-content: space-between;
align-items: center;
}

@media (min-width: 1140px) {
header {
padding: 12px 20px;
width: 171px;
flex-direction: column;
}

.button-container {
flex-direction: column;
width: 100%;
}
}

@media (min-width: 1300px) {
header {
width: 251px;
}
}
</style>
Loading
Loading