Added settings for newsletter header, title style, and feature image (#1993)

refs https://github.com/TryGhost/Team/issues/755
reqs https://github.com/TryGhost/Ghost/pull/13006

- updated settings model to match new server-side settings
- updated email customisation modal behind the dev experiments flag
  - adjusted layout to move to a fixed top bar and scrollable sidebar
  - added image upload, toggles and selections for new settings
  - updated preview to match selected settings

Co-authored-by: Sanne de Vries <sannedv@protonmail.com>
This commit is contained in:
Kevin Ansfield 2021-06-07 16:36:21 +01:00 committed by GitHub
parent 230058d6ec
commit b2b66490b7
13 changed files with 667 additions and 16 deletions

View File

@ -4,6 +4,10 @@ import XFileInput from 'emberx-file-input/components/x-file-input';
// upgraded to emberx-file-input@1.2.0
export default XFileInput.extend({
didInsertElement() {
this.onInsert?.(this.element.querySelector('input[type="file"]'));
},
change(e) {
let action = this.action;
let files = this.files(e);

View File

@ -4,5 +4,11 @@
files=this.files
isUploading=this._uploadFiles.isRunning
progressBar=(component "gh-progress-bar" percentage=this.uploadPercentage)
setFiles=(action 'setFiles')
setFiles=(action "setFiles")
registerFileInput=(action "registerFileInput")
triggerFileDialog=(action "triggerFileDialog")
imageExtensions=this.imageExtensions
imageMimeTypes=this.imageMimeTypes
iconExtensions=this.iconExtensions
iconMimeTypes=this.iconMimeTypes
)}}

View File

@ -1,6 +1,12 @@
import Component from '@ember/component';
import EmberObject from '@ember/object';
import ghostPaths from 'ghost-admin/utils/ghost-paths';
import {
ICON_EXTENSIONS,
ICON_MIME_TYPES,
IMAGE_EXTENSIONS,
IMAGE_MIME_TYPES
} from 'ghost-admin/components/gh-image-uploader';
import {all, task} from 'ember-concurrency';
import {get} from '@ember/object';
import {isArray} from '@ember/array';
@ -89,6 +95,11 @@ export default Component.extend({
if (!this.paramsHash) {
this.set('paramsHash', {purpose: 'image'});
}
this.set('imageExtensions', IMAGE_EXTENSIONS);
this.set('imageMimeTypes', IMAGE_MIME_TYPES);
this.set('iconExtensions', ICON_EXTENSIONS);
this.set('iconMimeTypes', ICON_MIME_TYPES);
},
didReceiveAttrs() {
@ -105,6 +116,20 @@ export default Component.extend({
},
actions: {
registerFileInput(input) {
this.fileInput = input;
},
triggerFileDialog() {
if (!this.fileInput) {
// eslint-disable-next-line
console.error('When using uploader.triggerFileDialog you must call uploader.registerFileInput first');
return;
}
this.fileInput.click();
},
setFiles(files, resetInput) {
this._setFiles(files);

View File

@ -0,0 +1,300 @@
<div class="modal-body modal-fullsettings labs-newsletter-settings">
<div class="flex items-center justify-between w-100 modal-fullsettings-topbar">
<h2 class="modal-fullsettings-heading">Email newsletter design</h2>
<div class="flex items-center">
<button
class="gh-btn mr3"
{{on "click" (action "closeModal")}}
{{!-- disable mouseDown so it does not trigger focus-out validations --}}
{{on "mousedown" (optional this.noop)}}
data-test-button="cancel-custom-view-form"
>
<span>Cancel</span>
</button>
<GhTaskButton
@buttonText="Save and close"
@successText="Saved"
@task={{this.saveSettings}}
@idleClass="gh-btn-primary"
@class="gh-btn gh-btn-icon"
data-test-button="save-members-modal-setting"
/>
</div>
</div>
<div class="modal-fullsettings-body">
<div class="modal-fullsettings-sidebar with-footer">
<div>
<fieldset class="modal-fullsettings-form">
<div class="modal-fullsettings-section first">
<GhFormGroup @classNames="vertical">
<h4 class="modal-fullsettings-title">Header image</h4>
<GhUploader
@extensions={{this.imageExtensions}}
@paramsHash={{hash purpose="image"}}
@onComplete={{fn this.imageUploaded "headerImage"}}
as |uploader|
>
<div class="modal-fullsettings-uploader">
{{#if uploader.isUploading}}
<div class="gh-portal-button-icon">
<div class="gh-loading-spinner"></div>
</div>
{{else if this.headerImage}}
<div class="gh-header-img-container">
<img
class="gh-header-img-thumbnail"
src={{this.headerImage}}
alt="header image"
data-test-img="header"
>
<button type="button" class="gh-btn gh-header-img-deleteicon" {{on "click" (fn this.changeSetting "headerImage" null)}}>
<span> {{svg-jar "trash" class="w5 h5"}} </span>
</button>
</div>
{{else}}
<button type="button" class="gh-btn gh-header-img-uploadicon" data-tooltip="Upload image" {{on "click" uploader.triggerFileDialog}} data-test-image-upload-btn="header-image">
<span>{{svg-jar "upload-fill" class="w5 h5"}}</span>
</button>
<div style="display:none">
<GhFileInput
@multiple={{false}}
@action={{uploader.setFiles}}
@accept={{uploader.imageMimeTypes}}
@onInsert={{uploader.registerFileInput}}
data-test-file-input="icon" />
</div>
{{/if}}
<div>
<h4>An optional branded image</h4>
<p>For best result use 1200x600 PNG image</p>
</div>
</div>
</GhUploader>
</GhFormGroup>
<GhFormGroup>
<h4 class="modal-fullsettings-title">Show publication icon</h4>
<div class="for-switch small {{if (not this.settings.icon) "disabled"}}">
<label class="switch" for="show-header">
<input
type="checkbox"
checked={{and this.showHeaderIcon this.settings.icon}}
id="show-header"
name="show-header"
disabled={{not this.settings.icon}}
{{on "click" (fn this.toggleSetting "showHeaderIcon")}}
>
<span class="input-toggle-component"></span>
</label>
</div>
</GhFormGroup>
<GhFormGroup>
<h4 class="modal-fullsettings-title">Show publication title</h4>
<div class="for-switch small">
<label class="switch" for="show-title">
<input
type="checkbox"
checked={{this.showHeaderTitle}}
id="show-title"
name="show-title"
{{on "click" (fn this.toggleSetting "showHeaderTitle")}}
>
<span class="input-toggle-component"></span>
</label>
</div>
</GhFormGroup>
</div>
<div class="modal-fullsettings-section divider-top">
<GhFormGroup>
<h4 class="modal-fullsettings-title">Show post feature image</h4>
<div class="for-switch small">
<label class="switch" for="show-feature-image">
<input
type="checkbox"
checked={{this.showFeatureImage}}
id="show-feature-image"
name="show-feature-image"
{{on "click" (fn this.toggleSetting "showFeatureImage")}}
>
<span class="input-toggle-component"></span>
</label>
</div>
</GhFormGroup>
<GhFormGroup @classNames="vertical">
<h4 class="modal-fullsettings-title gh-email-design-alignment">
<span>Post title style</span>
<div class="gh-btn-group icons">
<button type="button" class="gh-btn gh-btn-icon {{if (eq this.titleAlignment "left") "gh-btn-group-selected"}}" {{on "click" (fn this.changeSetting "titleAlignment" "left")}}><span>{{svg-jar "align-left"}}</span></button>
<button type="button" class="gh-btn gh-btn-icon {{if (eq this.titleAlignment "center") "gh-btn-group-selected"}}" {{on "click" (fn this.changeSetting "titleAlignment" "center")}}><span>{{svg-jar "align-center"}}</span></button>
</div>
</h4>
<div class="modal-fullsettings-radiogroup gh-email-design-typography">
<div class="gh-radio {{if (eq this.titleFontCategory "serif") "active"}}"
{{on "click" (fn this.changeSetting "titleFontCategory" "serif")}}
>
<div class="gh-radio-content serif">
<div class="gh-radio-label">
<span class="sample title">Aa</span>
<div class="description">
<h4>Elegant serif</h4>
<p>Beautiful lines with great readability</p>
</div>
</div>
</div>
<div class="gh-radio-button"></div>
</div>
<div class="gh-radio {{if (eq this.titleFontCategory "sans_serif") "active"}}"
{{on "click" (fn this.changeSetting "titleFontCategory" "sans_serif")}}
>
<div class="gh-radio-content sans-serif">
<div class="gh-radio-label">
<span class="sample title">Aa</span>
<div class="description">
<h4>Clean sans-serif</h4>
<p>A more minimal style with sharp lines</p>
</div>
</div>
</div>
<div class="gh-radio-button"></div>
</div>
</div>
{{!-- <p>Font style for the email title</p> --}}
</GhFormGroup>
</div>
<div class="modal-fullsettings-section">
<GhFormGroup @classNames="vertical">
<h4 class="modal-fullsettings-title">Body style</h4>
<div class="modal-fullsettings-radiogroup gh-email-design-typography">
<div class="gh-radio {{if (eq this.bodyFontCategory "serif") "active"}}"
{{on "click" (fn this.changeSetting "bodyFontCategory" "serif")}}
>
<div class="gh-radio-content serif">
<div class="gh-radio-label">
<span class="sample">Aa</span>
<div class="description">
<h4>Elegant serif</h4>
<p>Beautiful lines with great readability</p>
</div>
</div>
</div>
<div class="gh-radio-button"></div>
</div>
<div class="gh-radio {{if (eq this.bodyFontCategory "sans_serif") "active"}}"
{{on "click" (fn this.changeSetting "bodyFontCategory" "sans_serif")}}
>
<div class="gh-radio-content sans-serif">
<div class="gh-radio-label">
<span class="sample">Aa</span>
<div class="description">
<h4>Clean sans-serif</h4>
<p>A more minimal style with sharp lines</p>
</div>
</div>
</div>
<div class="gh-radio-button"></div>
</div>
</div>
{{!-- <p>Font style for the email body content</p> --}}
</GhFormGroup>
</div>
<div class="modal-fullsettings-section divider-top">
<GhFormGroup @classNames="vertical">
<h4 class="modal-fullsettings-title">Email footer</h4>
<KoenigBasicHtmlInput
@name="footer"
@html={{this.footerContent}}
@class="miw-100 form-text gh-members-emailsettings-footer-input"
@placeholder="Any extra information or legal text"
@onChange={{fn this.changeSetting "footerContent"}}
@onFocus={{this.handleInputFocus}}
@onBlur={{this.handleInputBlur}}
/>
</GhFormGroup>
</div>
</fieldset>
</div>
<div class="modal-fullsettings-section gh-members-emailsettings-footer">
<GhFormGroup>
<div class="gh-members-emailsettings-promotelabel">
<span>{{svg-jar "heart"}}</span>
<div>
<h4 class="modal-fullsettings-title">Promote independent publishing</h4>
<p>Show youre a part of the indie publishing movement with a small badge in the footer</p>
</div>
</div>
<div class="for-switch small">
<label
class="switch"
for="promote-ghost"
>
<input
type="checkbox"
checked={{this.showBadge}}
id="promote-ghost"
name="promote-ghost"
{{on "click" (fn this.toggleSetting "showBadge")}}
>
<span class="input-toggle-component"></span>
</label>
</div>
</GhFormGroup>
</div>
</div>
<div class="modal-fullsettings-main">
<div class="modal-fullsettings-preview-container gh-members-emailpreview">
<div class="gh-members-emailpreview-container">
<div class="gh-members-emailpreview-faux">
<p>
<span class="strong">{{this.config.blogTitle}}</span> &lt;{{this.settings.membersFromAddress}}&gt;
</p>
<p><span class="dark">To:</span> Jamie Larson &lt;jamie@example.com&gt;</p>
</div>
<div class="gh-members-emailpreview-contents">
{{#if this.headerImage}}
<div class="gh-members-emailpreview-header-image">
<img src={{this.headerImage}}>
</div>
{{/if}}
{{#if this.showHeader}}
<div class="gh-members-emailpreview-header">
{{#if (and this.settings.icon this.showHeaderIcon)}}
<img src={{this.settings.icon}} />
{{/if}}
{{#if this.showHeaderTitle}}
<h4>{{this.config.blogTitle}}</h4>
{{/if}}
</div>
{{/if}}
<div class="gh-members-emailpreview-title {{if (eq this.titleAlignment "left") "gh-members-emailpreview-title-left"}}">
<h2 class="{{if (eq this.titleFontCategory "serif") "serif"}}">Your email newsletter</h2>
<p>
<span>By {{if this.session.user.name this.session.user.name this.session.user.email}} {{this.currentDate}}  </span> <a href="javascript:">View online →</a>
</p>
</div>
{{#if this.showFeatureImage}}
<div class="gh-members-emailpreview-featureimage" style={{this.featureImageStyle}}></div>
{{/if}}
<div class="gh-members-emailpreview-content {{if (eq this.bodyFontCategory "sans_serif") "sans-serif"}}">
<p>This is what your content will look like when you send one of your posts as an email newsletter to your subscribers.</p>
<p>Over there on the left youll see some settings that allow you to customise the look and feel of this template to make it perfectly suited to your brand. Email templates are exceptionally finnicky to make, but weve spent a long time optimising this one to make it work beautifully across devices, email clients and content types.</p>
<p>So, you can trust that every email you send with Ghost will look great and work well. Just like the rest of your site.</p>
</div>
<div class="gh-members-emailpreview-footer">
<div class="gh-members-emailpreview-footercontent">
{{{this.footerContent}}}
</div>
<div class="gh-members-emailpreview-footersite">
<span>{{this.config.blogTitle}} &copy; </span> <a href="javascript:">Unsubscribe</a>
</div>
</div>
<div class="gh-members-emailpreview-badge {{if (not this.showBadge) "hide"}}">
<a href="javascript:"><svg viewBox="0 0 156 156"><g fill="none" fill-rule="evenodd"><rect fill="#15212B" width="156" height="156" rx="27"></rect><g transform="translate(36 36)" fill="#F6F8FA"><path d="M0 71.007A4.004 4.004 0 014 67h26a4 4 0 014 4.007v8.986A4.004 4.004 0 0130 84H4a4 4 0 01-4-4.007v-8.986zM50 71.007A4.004 4.004 0 0154 67h26a4 4 0 014 4.007v8.986A4.004 4.004 0 0180 84H54a4 4 0 01-4-4.007v-8.986z"></path><rect y="34" width="84" height="17" rx="4"></rect><path d="M0 4.007A4.007 4.007 0 014.007 0h41.986A4.003 4.003 0 0150 4.007v8.986A4.007 4.007 0 0145.993 17H4.007A4.003 4.003 0 010 12.993V4.007z"></path><rect x="67" width="17" height="17" rx="4"></rect></g></g></svg> <span>Publish with Ghost</span></a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,92 @@
import ModalComponent from 'ghost-admin/components/modal-base';
import moment from 'moment';
// TODO: expose this via a helper
import {IMAGE_EXTENSIONS} from 'ghost-admin/components/gh-image-uploader';
import {action} from '@ember/object';
import {htmlSafe} from '@ember/template';
import {inject as service} from '@ember/service';
import {task} from 'ember-concurrency-decorators';
import {tracked} from '@glimmer/tracking';
export default class ModalEmailDesignSettings extends ModalComponent {
@service config;
@service ghostPaths;
@service session;
@service settings;
@tracked headerImage = this.settings.get('newsletterHeaderImage');
@tracked showHeaderIcon = this.settings.get('newsletterShowHeaderIcon');
@tracked showHeaderTitle = this.settings.get('newsletterShowHeaderTitle');
@tracked titleFontCategory = this.settings.get('newsletterTitleFontCategory');
@tracked titleAlignment = this.settings.get('newsletterTitleAlignment');
@tracked showFeatureImage = this.settings.get('newsletterShowFeatureImage');
@tracked bodyFontCategory = this.settings.get('newsletterBodyFontCategory');
@tracked footerContent = this.settings.get('newsletterFooterContent');
@tracked showBadge = this.settings.get('newsletterShowBadge');
currentDate = moment().format('D MMM YYYY');
imageExtensions = IMAGE_EXTENSIONS;
get showHeader() {
return (this.showHeaderIcon && this.settings.get('icon')) || this.showHeaderTitle;
}
get featureImageUrl() {
// keep path separate so asset rewriting correctly picks it up
let imagePath = '/img/user-cover.png';
let fullPath = this.ghostPaths.assetRoot.replace(/\/$/, '') + imagePath;
return fullPath;
}
get featureImageStyle() {
return htmlSafe(`background-image: url(${this.featureImageUrl})`);
}
@action
toggleSetting(setting, event) {
this[setting] = event.target.checked;
}
@action
changeSetting(setting, value) {
this[setting] = value;
}
@action
imageUploaded(setting, images) {
if (images[0]) {
this[setting] = images[0].url;
}
}
@action
handleInputFocus() {
this._removeShortcuts();
}
@action
handleInputBlur() {
this._setupShortcuts();
}
@action
confirm() {
this.saveSettings.perform();
}
@task({drop: true})
*saveSettings() {
this.settings.set('newsletterHeaderImage', this.headerImage);
this.settings.set('newsletterShowHeaderIcon', this.showHeaderIcon);
this.settings.set('newsletterShowHeaderTitle', this.showHeaderTitle);
this.settings.set('newsletterTitleFontCategory', this.titleFontCategory);
this.settings.set('newsletterTitleAlignment', this.titleAlignment);
this.settings.set('newsletterShowFeatureImage', this.showFeatureImage);
this.settings.set('newsletterBodyFontCategory', this.bodyFontCategory);
this.settings.set('newsletterFooterContent', this.footerContent);
this.settings.set('newsletterShowBadge', this.showBadge);
yield this.settings.save();
this.closeModal();
}
}

View File

@ -145,7 +145,7 @@
<div class="gh-members-emailpreview-title">
<h2>Your email newsletter</h2>
<p>
<span>By {{if this.session.user.name this.session.user.name this.session.user.email}} {{this.currentDate}}  </span> <a href="javascript:">View online →</a>
<span>By {{if this.session.user.name this.session.user.name this.session.user.email}} {{this.currentDate}} </span> <a href="javascript:">View online →</a>
</p>
</div>
<div class="gh-members-emailpreview-content {{if (eq this.bodyFontCategory "sans_serif") "sans-serif"}}">

View File

@ -77,9 +77,15 @@ export default Model.extend(ValidationEngine, {
* Newsletter settings
*/
newsletterShowHeader: attr('boolean'),
newsletterHeaderImage: attr('string'),
newsletterShowHeaderIcon: attr('boolean'),
newsletterShowHeaderTitle: attr('boolean'),
newsletterTitleFontCategory: attr('string'),
newsletterTitleAlignment: attr('string'),
newsletterShowFeatureImage: attr('boolean'),
newsletterBodyFontCategory: attr('string'),
newsletterShowBadge: attr('boolean'),
newsletterFooterContent: attr('string'),
newsletterShowBadge: attr('boolean'),
/**
* OAuth settings
*/

View File

@ -227,7 +227,7 @@
}
/* Full screen setting modal with preview. Used in e.g. Portal
/* Full screen setting modal with preview. Used in e.g. Portal
/* settings, Email design settings etc.
/* ---------------------------------------------------------- */
.modal-fullsettings {
@ -241,6 +241,9 @@
padding: 0;
flex-grow: 1;
}
.labs-newsletter-settings .modal-fullsettings-body {
overflow: hidden;
}
.modal-fullsettings-body .form-group.space-l {
margin-bottom: 1.9em;
@ -266,6 +269,10 @@
padding: 0px 24px 20px;
width: 362px;
}
.labs-newsletter-settings .modal-fullsettings-sidebar {
width: 400px;
overflow-y: auto;
}
.modal-fullsettings-sidebar.with-footer {
justify-content: space-between;
@ -275,6 +282,9 @@
height: 66px;
padding: 0 24px;
}
.labs-newsletter-settings .modal-fullsettings-topbar {
border-bottom: 1px solid var(--whitegrey);
}
.modal-fullsettings-heading {
display: flex;
@ -284,6 +294,9 @@
padding: 0 24px;
margin: 0 -24px 1px;
}
.labs-newsletter-settings .modal-fullsettings-heading {
height: 66px;
}
.modal-fullsettings-form {
min-width: 292px;
@ -294,14 +307,22 @@
padding: 0 24px;
}
/* labs-newsletter-settings - delete all when removing flag */
.modal-fullsettings-section.first {
margin-top: 8px;
}
.labs-newsletter-settings .modal-fullsettings-section.first {
margin-top: 24px;
}
/* end delete all */
.modal-fullsettings-section.divider-top {
border-top: 1px solid var(--whitegrey);
padding-top: 16px;
}
.labs-newsletter-settings .modal-fullsettings-section.divider-top {
padding-top: 24px;
}
.modal-fullsettings-sectionheading {
font-size: 1.2rem;
@ -319,6 +340,9 @@
padding: 0;
margin-bottom: 0;
}
.labs-newsletter-settings .modal-fullsettings-section .form-group {
margin-bottom: 20px;
}
.modal-fullsettings-section .form-group > p {
font-size: 1.25rem !important;
@ -365,6 +389,99 @@
margin: 0 12px 0 0;
}
.labs-newsletter-settings .modal-fullsettings-uploader {
display: flex;
align-items: center;
margin: 18px 0 0;
padding: 3px;
border: 1px solid var(--whitegrey);
border-radius: 3px;
}
.labs-newsletter-settings .gh-header-img-uploadicon,
.labs-newsletter-settings .gh-header-img-uploadicon:hover,
.labs-newsletter-settings .gh-header-img-uploadicon:focus {
width: 56px;
height: 44px;
margin-right: 11px;
border: 1px dashed var(--lightgrey);
background: transparent;
box-shadow: none;
}
.labs-newsletter-settings .gh-header-img-uploadicon span {
display: flex;
justify-content: center;
align-items: center;
}
.labs-newsletter-settings .gh-header-img-uploadicon span svg {
width: 18px;
height: 18px;
fill: var(--darkgrey);
}
.labs-newsletter-settings .gh-header-img-uploadicon:hover span svg {
fill: var(--darkgrey);
}
.labs-newsletter-settings .gh-header-img-container {
height: 44px;
}
.labs-newsletter-settings .gh-header-img-thumbnail {
display: inline-block;
width: 56px;
height: 44px;
margin: 0 11px 0 0;
border: 1px solid var(--whitegrey);
cursor: pointer;
background-position: center;
object-fit: cover;
border-radius: 3px;
}
.labs-newsletter-settings .gh-header-img-thumbnail svg path {
stroke: var(--midlightgrey-d1);
}
.labs-newsletter-settings .gh-header-img-deleteicon {
position: absolute;
left: 4px;
width: 56px;
height: 44px;
background: var(--black) !important;
opacity: 0;
}
.labs-newsletter-settings .gh-header-img-deleteicon:hover {
opacity: 1;
}
.labs-newsletter-settings .gh-header-img-deleteicon span {
display: flex;
justify-content: center;
align-items: center;
}
.labs-newsletter-settings .gh-header-img-deleteicon span svg {
width: 18px;
height: 18px;
}
.modal-fullsettings-uploader h4 {
margin: 0 !important;
padding: 0;
font-size: 1.3rem;
line-height: 1.4em;
}
.modal-fullsettings-uploader p {
margin: 0 !important;
padding: 0;
font-size: 1.2rem !important;
}
.modal-fullsettings-main {
display: flex;
flex-direction: column;
@ -379,6 +496,9 @@
height: calc(100vh - 126px);
overflow-y: scroll;
}
.labs-newsletter-settings .modal-fullsettings-preview-container {
height: 100vh;
}
.modal-fullsettings-preview-hidescrollbar {
overflow: hidden;
@ -387,6 +507,9 @@
border: 1px solid var(--whitegrey);
border-radius: 5px;
}
.labs-newsletter-settings .modal-fullsettings-preview-hidescrollbar {
height: 100vh;
}
.modal-fullsettings-preview-hidescrollbar .modal-fullsettings-preview-container {
border: none;
@ -448,4 +571,4 @@
flex: 1;
margin-right: 10px;
}
}
}

View File

@ -58,7 +58,7 @@
@media (max-width: 1100px) {
.members-list {
border-bottom: none
border-bottom: none
}
}
@ -780,7 +780,7 @@ textarea.gh-member-details-textarea {
}
.gh-member-btn-expandfeed {
margin: 8px 0;
margin: 8px 0;
}
@ -1180,6 +1180,13 @@ p.gh-members-import-errordetail:first-of-type {
/* Email newsletter design settings
/* -------------------------------------------------------- */
.labs-newsletter-settings .gh-email-design-alignment {
display: flex;
justify-content: space-between;
align-items: center;
margin: -4px 0 0 0;
}
.gh-email-design-typography .gh-radio {
display: flex;
align-items: center;
@ -1188,18 +1195,44 @@ p.gh-members-import-errordetail:first-of-type {
padding: 0;
margin-bottom: 12px;
}
.labs-newsletter-settings .gh-email-design-typography .gh-radio {
margin-bottom: 2px;
}
.gh-email-design-typography .gh-radio-content {
border: 1px solid var(--whitegrey);
border-radius: 3px;
border-radius: 3px; /* labs-newsletter-settings - delete line when removing flag */
margin: 0 -32px 0 0;
}
/* labs-newsletter-settings - delete all when removing flag */
.labs-newsletter-settings .gh-email-design-typography .gh-radio-content {
border-radius: inherit;
}
/* end delete all */
.labs-newsletter-settings .gh-email-design-typography .gh-radio-content.serif {
border-top-left-radius: 3px;
border-top-right-radius: 3px;
}
.labs-newsletter-settings .gh-email-design-typography .gh-radio-content.sans-serif {
border-bottom-left-radius: 3px;
border-bottom-right-radius: 3px;
}
.labs-newsletter-settings .gh-email-design-typography .active {
margin: 0 2px 2px;
}
.gh-email-design-typography .active .gh-radio-content {
border: 1px solid transparent;
box-shadow: 0px 0px 0px 2px var(--green);
}
.labs-newsletter-settings .gh-email-design-typography .active .gh-radio-label {
margin: 0 -2px;
}
.gh-email-design-typography .gh-radio-button {
margin-right: 12px;
opacity: 0;
@ -1219,6 +1252,13 @@ p.gh-members-import-errordetail:first-of-type {
width: 44px;
text-align: center;
}
.labs-newsletter-settings .gh-email-design-typography .gh-radio-label .sample {
font-weight: 400;
}
.labs-newsletter-settings .gh-email-design-typography .gh-radio-label .sample.title {
font-weight: 600;
}
.gh-email-design-typography .gh-radio-label .description h4 {
font-size: 1.3rem;
@ -1227,7 +1267,8 @@ p.gh-members-import-errordetail:first-of-type {
line-height: 1.4em;
}
.gh-email-design-typography .gh-radio-label.serif .description h4 {
.gh-email-design-typography .gh-radio-label.serif .description h4,
.labs-newsletter-settings .gh-email-design-typography .gh-radio-content.serif .description h4 {
font-family: Georgia, 'Times New Roman', Times, serif;
font-size: 1.3rem;
}
@ -1238,7 +1279,8 @@ p.gh-members-import-errordetail:first-of-type {
padding: 0;
}
.gh-email-design-typography .gh-radio-label.serif .description p {
.gh-email-design-typography .gh-radio-label.serif .description p,
.labs-newsletter-settings .gh-email-design-typography .gh-radio-content.serif .description p {
font-size: 1.25rem !important;
margin: 0;
padding: 0;
@ -1253,7 +1295,7 @@ p.gh-members-import-errordetail:first-of-type {
.gh-members-emailsettings-footer-input p {
height: 108px;
overflow-y: scroll;
overflow-y: auto;
}
.gh-members-emailsettings-footer-input p {
@ -1266,6 +1308,10 @@ p.gh-members-import-errordetail:first-of-type {
padding-top: 20px;
margin-bottom: 4px;
}
.labs-newsletter-settings .gh-members-emailsettings-footer {
padding: inherit;
margin: 0px -24px 4px;
}
.gh-members-emailsettings-footer .form-group {
align-items: flex-start;
@ -1406,6 +1452,9 @@ p.gh-members-import-errordetail:first-of-type {
align-items: center;
padding: 50px 0 40px;
}
.labs-newsletter-settings .gh-members-emailpreview-title-left {
align-items: flex-start;
}
.gh-members-emailpreview-title h2 {
font-size: 4.2rem;
@ -1438,6 +1487,15 @@ p.gh-members-import-errordetail:first-of-type {
color: #15212A;
}
.labs-newsletter-settings .gh-members-emailpreview-featureimage {
width: 100%;
max-width: 600px;
height: 300px;
margin-bottom: 1.7em;
background: #fafafa no-repeat 50%;
background-size: cover;
}
.gh-members-emailpreview-content {
padding-bottom: 20px;
border-bottom: 1px solid #e5eff5;
@ -1713,4 +1771,4 @@ p.gh-members-import-errordetail:first-of-type {
.gh-member-product-form-block .form-group:last-of-type {
margin: 0;
}
}

View File

@ -421,7 +421,7 @@ Usage: CTA buttons grouped together horizontally.
border-radius: 0;
height: 30px;
line-height: 30px;
border-radius: 2px;
border-radius: 3px;
background: transparent !important;
font-weight: 500 !important;
}
@ -438,6 +438,31 @@ Usage: CTA buttons grouped together horizontally.
fill: var(--black);
}
.gh-btn-group.icons .gh-btn {
margin: 3px;
border-radius: 3px;
}
.gh-btn-group.icons .gh-btn span {
height: 28px;
padding: 0 10px;
}
.gh-btn-group.icons .gh-btn-icon svg {
width: 18px;
height: 18px;
margin-right: 0;
fill: var(--midgrey);
}
.gh-btn-group.icons .gh-btn-group-selected svg {
fill: var(--black);
}
.gh-btn-group.icons .gh-btn-icon svg path {
stroke: none;
}
.gh-btn-block + .gh-btn-block {
margin-top: 5px;
}

View File

@ -45,8 +45,14 @@
{{#if this.showEmailDesignSettings}}
<GhFullscreenModal @modifier="full-overlay portal-settings">
<ModalEmailDesignSettings
@closeModal={{this.toggleEmailDesignSettings}}
/>
{{#if (enable-developer-experiments)}}
<ModalEmailDesignSettingsLabs
@closeModal={{this.toggleEmailDesignSettings}}
/>
{{else}}
<ModalEmailDesignSettings
@closeModal={{this.toggleEmailDesignSettings}}
/>
{{/if}}
</GhFullscreenModal>
{{/if}}

View File

@ -0,0 +1,3 @@
<svg width="24" height="24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M1 6a1 1 0 011-1h20a1 1 0 110 2H2a1 1 0 01-1-1zM6 12.5a1 1 0 011-1h10a1 1 0 110 2H7a1 1 0 01-1-1zM1 19a1 1 0 011-1h20a1 1 0 110 2H2a1 1 0 01-1-1z"/>
</svg>

After

Width:  |  Height:  |  Size: 282 B

View File

@ -0,0 +1,3 @@
<svg width="24" height="24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M1 6a1 1 0 011-1h20a1 1 0 110 2H2a1 1 0 01-1-1zM1 12.5a1 1 0 011-1h12a1 1 0 110 2H2a1 1 0 01-1-1zM1 19a1 1 0 011-1h20a1 1 0 110 2H2a1 1 0 01-1-1z"/>
</svg>

After

Width:  |  Height:  |  Size: 283 B