Skip to content

Commit

Permalink
Anchor FM Theme Font Pairings (#48661)
Browse files Browse the repository at this point in the history
* add(anchorfm-font-pairings) proof of concept for anchorfm specific font pairings

* add(anchorfm-font-pairings) adding correct font pairing and font pairing hook

* add(anchorfm-font-pairings) removing unnecessary constant, adding back space

* add(anchor-fm-font-pairings) fixing linting errors

* add(anchor-fm-font-pairings) fixing linting errors

* add(anchor-fm-font-pairings) fixing linting errors
  • Loading branch information
krymson24 authored Jan 14, 2021
1 parent 3fa3030 commit da4bd5e
Show file tree
Hide file tree
Showing 7 changed files with 103 additions and 63 deletions.
8 changes: 4 additions & 4 deletions client/landing/gutenboarding/available-designs-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -295,8 +295,8 @@
"template": "gilbert",
"theme": "gilbert",
"fonts": {
"headings": "Chivo",
"base": "Open Sans"
"headings": "Roboto",
"base": "Roboto"
},
"categories": [ "featured" ],
"is_premium": false,
Expand All @@ -308,8 +308,8 @@
"template": "riley",
"theme": "riley",
"fonts": {
"headings": "Fira Sans",
"base": "Fira Sans"
"headings": "Raleway",
"base": "Cabin"
},
"categories": [ "featured" ],
"is_premium": false,
Expand Down
17 changes: 16 additions & 1 deletion client/landing/gutenboarding/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import type { ValuesType } from 'utility-types';
*
*/
export const FLOW_ID = 'gutenboarding';
export const ANCHOR_FM_FLOW_ID = 'anchor-fm';

const fontTitles: Partial< Record< Font, string > > = {
'Playfair Display': 'Playfair',
Expand Down Expand Up @@ -48,6 +47,22 @@ export const fontPairings = [
},
] as const;

/**
* Pairings of fontFamilies for AnchorFM onboarding
*
* To get the name of the font for display, use `getFontTitle( fontName )`.
*/
export const anchorFmFontPairings = [
{
headings: 'Roboto',
base: 'Roboto',
},
{
headings: 'Raleway',
base: 'Cabin',
},
] as const;

export type Font = ValuesType< ValuesType< typeof fontPairings > >;
export interface FontPair {
headings: Font;
Expand Down
13 changes: 13 additions & 0 deletions client/landing/gutenboarding/fonts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/**
* Internal dependencies
*/
import { fontPairings, anchorFmFontPairings } from '../gutenboarding/constants';
import { useIsAnchorFm } from '../gutenboarding/path';

export function useFontPairings() {
const isAnchorFmSignup = useIsAnchorFm();
const effectiveFontPairings = isAnchorFmSignup
? [ ...fontPairings, ...anchorFmFontPairings ]
: fontPairings;
return effectiveFontPairings;
}
6 changes: 4 additions & 2 deletions client/landing/gutenboarding/gutenboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,15 @@ import { useI18n } from '@automattic/react-i18n';
import Header from './components/header';
import SignupForm from './components/signup-form';
import { name, settings } from './onboarding-block';
import { fontPairings, getFontTitle } from './constants';
import { FontPair, getFontTitle } from './constants';
import useOnSiteCreation from './hooks/use-on-site-creation';
import { usePageViewTracksEvents } from './hooks/use-page-view-tracks-events';
import useSignup from './hooks/use-signup';
import useOnSignup from './hooks/use-on-signup';
import useOnLogin from './hooks/use-on-login';
import useSiteTitle from './hooks/use-site-title';
import useTrackOnboardingStart from './hooks/use-track-onboarding-start';
import { useFontPairings } from '../gutenboarding/fonts';

import './style.scss';

Expand All @@ -40,11 +41,12 @@ const Gutenboard: React.FunctionComponent = () => {
useTrackOnboardingStart();
useSiteTitle();
const { showSignupDialog, onSignupDialogClose } = useSignup();
const effectiveFontPairings = useFontPairings();

// TODO: Explore alternatives for loading fonts and optimizations
// TODO: Don't load like this
React.useEffect( () => {
fontPairings.forEach( ( { base, headings } ) => {
effectiveFontPairings.forEach( ( { base, headings }: FontPair ) => {
const linkBase = document.createElement( 'link' );
const linkHeadings = document.createElement( 'link' );

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@ import classnames from 'classnames';
import isShallowEqual from '@wordpress/is-shallow-equal';
import { useDispatch, useSelect } from '@wordpress/data';
import { useI18n } from '@automattic/react-i18n';
import { useFontPairings } from '../../fonts';

/**
* Internal dependencies
*/
import { fontPairings, getFontTitle, FontPair } from '../../constants';
import { getFontTitle, FontPair } from '../../constants';
import { STORE_KEY as ONBOARD_STORE } from '../../stores/onboard';

const FontSelect: React.FunctionComponent = () => {
Expand Down Expand Up @@ -57,6 +58,8 @@ const FontSelect: React.FunctionComponent = () => {
__( 'Select fonts' )
);

const effectiveFontPairings = useFontPairings();

const fontPairingsFilter = ( pair: FontPair ): boolean => {
if ( ! selectedDesignDefaultFonts ) {
return true;
Expand All @@ -83,30 +86,33 @@ const FontSelect: React.FunctionComponent = () => {
>
<span className="style-preview__font-option-contents">{ defaultFontOption }</span>
</Button>
{ fontPairings.filter( fontPairingsFilter ).map( ( fontPair ) => {
// Font pairs are objects, we need `isShallowEqual` as we can't guarantee referential equality
// (E.g. if `selectedFonts` is coming from persisted state)
const isSelected = !! selectedFonts && isShallowEqual( fontPair, selectedFonts );
const { headings, base } = fontPair;
{ /* https://github.com/microsoft/TypeScript/issues/36390 */ }
{ ( effectiveFontPairings as FontPair[] )
.filter( fontPairingsFilter )
.map( ( fontPair ) => {
// Font pairs are objects, we need `isShallowEqual` as we can't guarantee referential equality
// (E.g. if `selectedFonts` is coming from persisted state)
const isSelected = !! selectedFonts && isShallowEqual( fontPair, selectedFonts );
const { headings, base } = fontPair;

return (
<Button
className={ classnames( 'style-preview__font-option', {
'is-selected': isSelected,
} ) }
onClick={ () => setFonts( fontPair ) }
key={ headings + base }
>
<span className="style-preview__font-option-contents">
<span style={ { fontFamily: headings, fontWeight: 700 } }>
{ getFontTitle( headings ) }
return (
<Button
className={ classnames( 'style-preview__font-option', {
'is-selected': isSelected,
} ) }
onClick={ () => setFonts( fontPair ) }
key={ headings + base }
>
<span className="style-preview__font-option-contents">
<span style={ { fontFamily: headings, fontWeight: 700 } }>
{ getFontTitle( headings ) }
</span>
&nbsp;/&nbsp;
<span style={ { fontFamily: base } }>{ getFontTitle( base ) }</span>
</span>
&nbsp;/&nbsp;
<span style={ { fontFamily: base } }>{ getFontTitle( base ) }</span>
</span>
</Button>
);
} ) }
</Button>
);
} ) }
</div>
<div className="style-preview__font-options-mobile">
<Button
Expand Down Expand Up @@ -143,34 +149,36 @@ const FontSelect: React.FunctionComponent = () => {
>
<span className="style-preview__font-option-contents">{ defaultFontOption }</span>
</Button>
{ fontPairings.filter( fontPairingsFilter ).map( ( fontPair ) => {
// Font pairs are objects, we need `isShallowEqual` as we can't guarantee referential equality
// (E.g. if `selectedFonts` is coming from persisted state)
const isSelected = !! selectedFonts && isShallowEqual( fontPair, selectedFonts );
const { headings, base } = fontPair;
{ ( effectiveFontPairings as FontPair[] )
.filter( fontPairingsFilter )
.map( ( fontPair ) => {
// Font pairs are objects, we need `isShallowEqual` as we can't guarantee referential equality
// (E.g. if `selectedFonts` is coming from persisted state)
const isSelected = !! selectedFonts && isShallowEqual( fontPair, selectedFonts );
const { headings, base } = fontPair;

return (
<Button
className={ classnames(
'style-preview__font-option',
'style-preview__font-option-mobile',
{
'is-selected-dropdown-option': isSelected,
}
) }
onClick={ () => setFontsAndClose( fontPair ) }
key={ headings + base }
>
<span className="style-preview__font-option-contents">
<span style={ { fontFamily: headings, fontWeight: 700 } }>
{ getFontTitle( headings ) }
return (
<Button
className={ classnames(
'style-preview__font-option',
'style-preview__font-option-mobile',
{
'is-selected-dropdown-option': isSelected,
}
) }
onClick={ () => setFontsAndClose( fontPair ) }
key={ headings + base }
>
<span className="style-preview__font-option-contents">
<span style={ { fontFamily: headings, fontWeight: 700 } }>
{ getFontTitle( headings ) }
</span>
&nbsp;/&nbsp;
<span style={ { fontFamily: base } }>{ getFontTitle( base ) }</span>
</span>
&nbsp;/&nbsp;
<span style={ { fontFamily: base } }>{ getFontTitle( base ) }</span>
</span>
</Button>
);
} ) }
</Button>
);
} ) }
</div>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,18 @@ import { useLocale } from '@automattic/i18n-utils';
* Internal dependencies
*/
import { STORE_KEY } from '../../stores/onboard';
import { fontPairings } from '../../constants';
import type { Viewport } from './types';
import { useFontPairings } from '../../fonts';
import type { FontPair } from '../../constants';

function getFontsLoadingHTML() {
function getFontsLoadingHTML( effectiveFontPairings: readonly FontPair[] ) {
const baseURL = 'https://fonts.googleapis.com/css2';

// matrix: regular,bold * regular,italic
const axis = 'ital,wght@0,400;0,700;1,400;1,700';

// create a query for all fonts together
const query = fontPairings.reduce( ( acc, pairing ) => {
const query = effectiveFontPairings.reduce( ( acc, pairing ) => {
acc.push(
`family=${ encodeURI( pairing.headings ) }:${ axis }`,
`family=${ encodeURI( pairing.base ) }:${ axis }`
Expand All @@ -36,7 +37,7 @@ function getFontsLoadingHTML() {

// Chrome doesn't load the fonts in memory until they're actually used,
// this keeps the fonts used and ready in memory.
const fontsHolders = fontPairings.reduce( ( acc, pairing ) => {
const fontsHolders = ( effectiveFontPairings as FontPair[] ).reduce( ( acc, pairing ) => {
Object.values( pairing ).forEach( ( font ) => {
const fontHolder = document.createElement( 'div' );
fontHolder.style.fontFamily = font;
Expand All @@ -62,6 +63,7 @@ const Preview: React.FunctionComponent< Props > = ( { viewport } ) => {
);

const iframe = React.useRef< HTMLIFrameElement >( null );
const effectiveFontPairings = useFontPairings();

React.useEffect(
() => {
Expand Down Expand Up @@ -98,7 +100,7 @@ const Preview: React.FunctionComponent< Props > = ( { viewport } ) => {
return;
}
const html = await resp.text();
const { head, fontsHolders } = getFontsLoadingHTML();
const { head, fontsHolders } = getFontsLoadingHTML( effectiveFontPairings );
// the browser automatically moves the head code to the <head />
setPreviewHtml( head + html + fontsHolders );
};
Expand Down
4 changes: 2 additions & 2 deletions client/landing/gutenboarding/path.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import type { ValuesType } from 'utility-types';
* Internal dependencies
*/
import config from 'calypso/config';
import { FLOW_ID, ANCHOR_FM_FLOW_ID } from '../gutenboarding/constants';
import { FLOW_ID } from '../gutenboarding/constants';

type PlanPath = Plans.PlanPath;

Expand Down Expand Up @@ -118,7 +118,7 @@ export function useIsAnchorFm(): boolean {

export function useOnboardingFlow(): string {
if ( useIsAnchorFm() ) {
return ANCHOR_FM_FLOW_ID;
return 'anchor-fm';
}
return FLOW_ID;
}
Expand Down

0 comments on commit da4bd5e

Please sign in to comment.