From 42bbba09d09f4cd8d88cd4a259a14fd21a569bdf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Igor=20Obradovi=C4=87?= Date: Fri, 8 Apr 2022 16:06:46 +0200 Subject: [PATCH 1/9] Add blog post - Adding fonts --- website/blog/2022-04-08-adding-fonts.md | 195 ++++++++++++++++++++++++ 1 file changed, 195 insertions(+) create mode 100644 website/blog/2022-04-08-adding-fonts.md diff --git a/website/blog/2022-04-08-adding-fonts.md b/website/blog/2022-04-08-adding-fonts.md new file mode 100644 index 000000000..b7cc03b90 --- /dev/null +++ b/website/blog/2022-04-08-adding-fonts.md @@ -0,0 +1,195 @@ +--- +title: Adding fonts +description: An intro to adding fonts to your project. +slug: adding-fonts +authors: iobrado +date: 2022-04-12 +tags: [eightshift, boilerplate, fonts] +hide_table_of_contents: false +--- + +Each project is different in its way. Logo, various fonts, etc. are what define the visual identity of your website. In this post, we'll cover adding fonts to a project. + + +### Importing fonts into your project +[Our documentation](/docs/basics/fonts) covers the required steps to add a font to your project, but here we'll cover the process in a bit more detail. To even start, we need a font (or two). For this example, I'll use **_SourceSansPro_** and **_NotoSerif_** downloaded from [Google Fonts](https://fonts.google.com/). These are in `.ttf` format, so convert them to `.woff` and `.woff2` however you can. We recommend the following tools: +- https://convertio.co/ttf-woff/ +- https://cloudconvert.com/ttf-to-woff +- https://everythingfonts.com/ttf-to-woff + +Fonts should go inside the **_/assets/fonts_** folder inside your theme. Paste the fonts you want to use there. You will also notice that this folder contains an **_index.js_** file. This file is used to import fonts into your project. Here's an example of how I imported my fonts: +```js +// SourceSansPro WOFF +import './SourceSansPro-Bold.woff'; +import './SourceSansPro-BoldItalic.woff'; +import './SourceSansPro-Italic.woff'; +import './SourceSansPro-Regular.woff'; +import './SourceSansPro-Light.woff'; +import './SourceSansPro-LightItalic.woff'; + +// SourceSansPro WOFF2 +import './SourceSansPro-Bold.woff2'; +import './SourceSansPro-BoldItalic.woff2'; +import './SourceSansPro-Italic.woff2'; +import './SourceSansPro-Regular.woff2'; +import './SourceSansPro-Light.woff2'; +import './SourceSansPro-LightItalic.woff2'; + +// NotoSerif WOFF +import './NotoSerif-Bold.woff'; +import './NotoSerif-BoldItalic.woff'; +import './NotoSerif-Italic.woff'; +import './NotoSerif-Regular.woff'; + +// NotoSerif WOFF2 +import './NotoSerif-Bold.woff2'; +import './NotoSerif-BoldItalic.woff2'; +import './NotoSerif-Italic.woff2'; +import './NotoSerif-Regular.woff2'; +``` + +To add these fonts as your base font and secondary font, go to the global manifest located in **_/src/Blocks_** and add the following inside `globalVariables`: +```json +"globalVariables": { + //... + "baseFont": "SourceSansPro", + "secondaryFont": "NotoSerif", + //... +} +``` + +Next, you can create a new file called **__typography.scss_** inside your **_/assets/styles/parts/utils/_** folder and add the following: + +```scss +@include font-face(global-settings(baseFont), 'SourceSansPro-Light', 300); +@include font-face(global-settings(baseFont), 'SourceSansPro-LightItalic', 300, italic); +@include font-face(global-settings(baseFont), 'SourceSansPro-Regular', 400); +@include font-face(global-settings(baseFont), 'SourceSansPro-Italic', 400, italic); +@include font-face(global-settings(baseFont), 'SourceSansPro-Bold', 700); +@include font-face(global-settings(baseFont), 'SourceSansPro-BoldItalic', 700, italic); + +@include font-face(global-settings(secondaryFont), 'NotoSerif-Bold', 700); +@include font-face(global-settings(secondaryFont), 'NotoSerif-BoldItalic', 700, italic); +@include font-face(global-settings(secondaryFont), 'NotoSerif-Italic', 400, italic); +@include font-face(global-settings(secondaryFont), 'NotoSerif-Regular', 400); +``` + +Because this is a new file, we have to include it. You can do that inside **_/assets/styles/parts/_shared.scss_** file: +```scss +// Project specific. +@import 'utils/shared-variables'; +@import 'utils/typography'; +``` + +Run `npm start` to rebuild your **_public_** folder and assets. If you did everything correctly, your build should pass and you will see your fonts inside the **_public_** folder. + +### Using only one font in a block + +There are multiple ways of using fonts in a block. The simplest example is if you have only one font you want to use for that specific block. In this case, we want Heading Block to only use NotoSerif. + +To make our secondary font available for use, first we need to define it as a variable. We can do that in **_/assets/styles/parts/utils/_shared-variables.scss_**. Here we can see that the base font is already defined, so all we need to do is add our secondary font below. + +To make things a bit more complicated, we may also want to rename `--global-font-family` CSS variable to `--base-font-family`. Just don't forget to search/replace this new variable name across your project! Once we're done, it should look like this: +```scss + --base-font-family: var(--global-base-font), -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, + Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; + + --secondary-font-family: var(--global-secondary-font), -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, + Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; +``` +After defining `--secondary-font-family` CSS variable, we can go to **_/src/Blocks/components/heading/heading-style.scss_** and add the following line inside `.heading` class: +```scss + font-family: var(--secondary-font-family); +``` + +And that's it! The Heading Block will now use the NotoSerif font. + +### Adding an option for selecting fonts + +In some cases, you may want to give users the option to choose between fonts that they want to use in their block. For this example, we'll use the `paragraph` block where we want users to have both SourceSansPro and NotoSerif font available. + +First step is to add a new attribute, options and CSS variable values in **_/src/Blocks/components/paragraph/manifest.json_**: +```json +//... + "attributes": { + //... + "paragraphFontFamily": { + "type": "string", + "default": "base" + } + }, + "options": { + //... + "paragraphFontFamily": [ + { + "label": "SourceSansPro", + "value": "base" + }, + { + "label": "NotoSerif", + "value": "secondary" + } + ], + //... + } +``` + +After defining a new attribute and options, we now have to add a variable to **_manifest.json_**. We can add it inside `variables`. This approach is slightly different from the one explained in [Modifying blocks](/blog/modifying-blocks) blog post. Here we can use `%value%` wildcard to dynamically add the selected value to our CSS variable. +```json +"paragraphFontFamily": [ + { + "variable": { + "paragraph-font-family": "var(--%value%-font-family)" + } + } +] +``` + +The next step is to go to **_/src/Blocks/components/paragraph/components/paragraph-options.js_** and add the new option for selecting fonts. The first thing we can add is a new attribute that will allow us to toggle showing the paragraph font family option on other blocks which are using the paragraph. There may be a case where we want only one font family, so this option may come in handy on some other blocks. +```js +const { + setAttributes, + //... + showParagraphFontFamily = true, + } = attributes; +``` + +After that, we need to fetch either the saved attribute value or get the default one from the manifest. We can do that with `checkAttr` helper and add it just below `paragraphColor` and `paragraphSize`. +```js + const paragraphFontFamily = checkAttr('paragraphFontFamily', attributes, manifest); +``` + +Now we have to add an actual option to the return statement which will allow us to choose between fonts. +```js + return ( + //... + {showParagraphFontFamily && + } + value={paragraphFontFamily} + options={getOption('paragraphFontFamily', attributes, manifest)} + onChange={(value) => setAttributes({ [getAttrKey('paragraphFontFamily', attributes, manifest)]: value })} + isClearable={false} + isSearchable={false} + simpleValue + /> + } + //... + ); +``` + +The option for selecting a font should now be available under Paragraph options. Saving the option now works, but the font stays the same both in the editor and on the frontend. The final step we need to make this work is to add a CSS variable to **_/src/Blocks/components/paragraph/paragraph-style.scss_**: +```scss +.paragraph { + //... + font-family: var(--paragraph-font-family, var(--base-font-family)); + //... +} +``` + +After adding this single line of CSS code, your new option for selecting fonts will now be fully functional. + +### Closing thoughts +Adding fonts to a project is something you will usually do only when setting up a new project and then forget about it. As you could see in this blog post, this isn't a complicated process, but it has a specific set of steps that have to be taken to make custom fonts work in your project. + +Of course, there are other ways to include fonts in your project, but the described process is the recommended one and is used by our team. This is the (Eightshift) Way. From 58da6774e80be4597824f556f85ed45c1ee5aed3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Igor=20Obradovi=C4=87?= Date: Mon, 11 Apr 2022 10:55:54 +0200 Subject: [PATCH 2/9] Apply suggestions from code review Co-authored-by: Mario Borna Mjertan --- website/blog/2022-04-08-adding-fonts.md | 44 ++++++++++++------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/website/blog/2022-04-08-adding-fonts.md b/website/blog/2022-04-08-adding-fonts.md index b7cc03b90..dc2c59d8f 100644 --- a/website/blog/2022-04-08-adding-fonts.md +++ b/website/blog/2022-04-08-adding-fonts.md @@ -12,12 +12,12 @@ Each project is different in its way. Logo, various fonts, etc. are what define ### Importing fonts into your project -[Our documentation](/docs/basics/fonts) covers the required steps to add a font to your project, but here we'll cover the process in a bit more detail. To even start, we need a font (or two). For this example, I'll use **_SourceSansPro_** and **_NotoSerif_** downloaded from [Google Fonts](https://fonts.google.com/). These are in `.ttf` format, so convert them to `.woff` and `.woff2` however you can. We recommend the following tools: +[Our documentation](/docs/basics/fonts) covers the necessary steps to add a font to your project, but here we'll cover the process in a bit more detail. To start, we need a font (or two). For this example, I'll use **_SourceSansPro_** and **_NotoSerif_** which I've downloaded from [Google Fonts](https://fonts.google.com/). These are in the `.ttf` format, so convert them to `.woff` and `.woff2. Whatever approach you use is okay - we recommend the following tools: - https://convertio.co/ttf-woff/ - https://cloudconvert.com/ttf-to-woff - https://everythingfonts.com/ttf-to-woff -Fonts should go inside the **_/assets/fonts_** folder inside your theme. Paste the fonts you want to use there. You will also notice that this folder contains an **_index.js_** file. This file is used to import fonts into your project. Here's an example of how I imported my fonts: +Fonts should go inside your theme's **_/assets/fonts_** folder. Copy the fonts you want to use there. You will also notice that this folder contains an **_index.js_** file. This file is used to import fonts into your project. Here's an example of how I imported my fonts: ```js // SourceSansPro WOFF import './SourceSansPro-Bold.woff'; @@ -51,10 +51,10 @@ import './NotoSerif-Regular.woff2'; To add these fonts as your base font and secondary font, go to the global manifest located in **_/src/Blocks_** and add the following inside `globalVariables`: ```json "globalVariables": { - //... + // ... "baseFont": "SourceSansPro", "secondaryFont": "NotoSerif", - //... + // ... } ``` @@ -87,9 +87,9 @@ Run `npm start` to rebuild your **_public_** folder and assets. If you did every There are multiple ways of using fonts in a block. The simplest example is if you have only one font you want to use for that specific block. In this case, we want Heading Block to only use NotoSerif. -To make our secondary font available for use, first we need to define it as a variable. We can do that in **_/assets/styles/parts/utils/_shared-variables.scss_**. Here we can see that the base font is already defined, so all we need to do is add our secondary font below. +To make our secondary font available for use, we need to first define it as a variable. We can do that in **_/assets/styles/parts/utils/_shared-variables.scss_**. We can see there that the base font is already defined, so all we need to do is add our secondary font below. -To make things a bit more complicated, we may also want to rename `--global-font-family` CSS variable to `--base-font-family`. Just don't forget to search/replace this new variable name across your project! Once we're done, it should look like this: +To make things a bit more consistent, we may also want to rename `--global-font-family` CSS variable to `--base-font-family`. Just don't forget to search/replace this new variable name across your project! Once we're done, it should look like this: ```scss --base-font-family: var(--global-base-font), -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; @@ -97,7 +97,7 @@ To make things a bit more complicated, we may also want to rename `--global-font --secondary-font-family: var(--global-secondary-font), -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; ``` -After defining `--secondary-font-family` CSS variable, we can go to **_/src/Blocks/components/heading/heading-style.scss_** and add the following line inside `.heading` class: +After defining `--secondary-font-family` CSS variable, we can go to **_/src/Blocks/components/heading/heading-style.scss_** and add the following rule to the `.heading` class: ```scss font-family: var(--secondary-font-family); ``` @@ -110,16 +110,16 @@ In some cases, you may want to give users the option to choose between fonts tha First step is to add a new attribute, options and CSS variable values in **_/src/Blocks/components/paragraph/manifest.json_**: ```json -//... +// ... "attributes": { - //... + // ... "paragraphFontFamily": { "type": "string", "default": "base" } }, "options": { - //... + // ... "paragraphFontFamily": [ { "label": "SourceSansPro", @@ -130,11 +130,11 @@ First step is to add a new attribute, options and CSS variable values in **_/src "value": "secondary" } ], - //... + // ... } ``` -After defining a new attribute and options, we now have to add a variable to **_manifest.json_**. We can add it inside `variables`. This approach is slightly different from the one explained in [Modifying blocks](/blog/modifying-blocks) blog post. Here we can use `%value%` wildcard to dynamically add the selected value to our CSS variable. +After defining a new attribute and options for the font family, we now have to add a variable to **_manifest.json_**. We can add it to the `variables` object. This approach is slightly different from the one explained in the [Modifying blocks](/blog/modifying-blocks) blog post. Here we can use `%value%` wildcard to dynamically add the selected value to our CSS variable. ```json "paragraphFontFamily": [ { @@ -145,7 +145,7 @@ After defining a new attribute and options, we now have to add a variable to **_ ] ``` -The next step is to go to **_/src/Blocks/components/paragraph/components/paragraph-options.js_** and add the new option for selecting fonts. The first thing we can add is a new attribute that will allow us to toggle showing the paragraph font family option on other blocks which are using the paragraph. There may be a case where we want only one font family, so this option may come in handy on some other blocks. +The next step is to go to **_/src/Blocks/components/paragraph/components/paragraph-options.js_** and add a control for the new font family option. The first thing we can add is a new attribute that will allow us to toggle showing the paragraph font family option on other blocks which are using the paragraph component. There might be a case where we want only one font family, so this option may come in handy in some other blocks. ```js const { setAttributes, @@ -154,15 +154,15 @@ const { } = attributes; ``` -After that, we need to fetch either the saved attribute value or get the default one from the manifest. We can do that with `checkAttr` helper and add it just below `paragraphColor` and `paragraphSize`. +After that, we need to fetch either the saved attribute value or get the default one from the manifest. We can do that with the `checkAttr` helper, adding it just below `paragraphColor` and `paragraphSize`. ```js const paragraphFontFamily = checkAttr('paragraphFontFamily', attributes, manifest); ``` -Now we have to add an actual option to the return statement which will allow us to choose between fonts. +Now we have to add an actual control to the options panel which will allow us to choose between fonts. ```js return ( - //... + // ... {showParagraphFontFamily && } @@ -174,22 +174,22 @@ Now we have to add an actual option to the return statement which will allow us simpleValue /> } - //... + // ... ); ``` -The option for selecting a font should now be available under Paragraph options. Saving the option now works, but the font stays the same both in the editor and on the frontend. The final step we need to make this work is to add a CSS variable to **_/src/Blocks/components/paragraph/paragraph-style.scss_**: +The control for selecting a font should now be available under Paragraph options. Saving the choice now works, but the font stays the same both in the editor and on the frontend. The final step we need to make this work is to add a CSS rule that consumes our variable to **_/src/Blocks/components/paragraph/paragraph-style.scss_**: ```scss .paragraph { - //... + // ... font-family: var(--paragraph-font-family, var(--base-font-family)); - //... + // ... } ``` After adding this single line of CSS code, your new option for selecting fonts will now be fully functional. ### Closing thoughts -Adding fonts to a project is something you will usually do only when setting up a new project and then forget about it. As you could see in this blog post, this isn't a complicated process, but it has a specific set of steps that have to be taken to make custom fonts work in your project. +Adding fonts to a project is something you will usually only do when setting up a new project and then forget about it. As you could see in this blog post, this isn't a complicated process, but it has a specific set of steps that have to be taken in order for custom fonts to work in your project. -Of course, there are other ways to include fonts in your project, but the described process is the recommended one and is used by our team. This is the (Eightshift) Way. +Of course, there are other ways to include fonts in your project, but the described process is what we recommend and use. This is the (Eightshift) Way. From efaa6dbcaec6d3f7873cbe8199997ec972fb5b35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Igor=20Obradovi=C4=87?= Date: Mon, 11 Apr 2022 16:16:46 +0200 Subject: [PATCH 3/9] Update website/blog/2022-04-08-adding-fonts.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Goran Alković <77000136+goranalkovic-infinum@users.noreply.github.com> --- website/blog/2022-04-08-adding-fonts.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/blog/2022-04-08-adding-fonts.md b/website/blog/2022-04-08-adding-fonts.md index dc2c59d8f..7e08cfb05 100644 --- a/website/blog/2022-04-08-adding-fonts.md +++ b/website/blog/2022-04-08-adding-fonts.md @@ -8,7 +8,7 @@ tags: [eightshift, boilerplate, fonts] hide_table_of_contents: false --- -Each project is different in its way. Logo, various fonts, etc. are what define the visual identity of your website. In this post, we'll cover adding fonts to a project. +Every project is unique. Logo, colors, fonts, etc. are what define the visual identity of your website. In this post, we'll cover adding fonts to a project. ### Importing fonts into your project From a5e9001fed43bdcb11c34275f21b67211927ffc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Igor=20Obradovi=C4=87?= Date: Mon, 11 Apr 2022 16:17:08 +0200 Subject: [PATCH 4/9] Update website/blog/2022-04-08-adding-fonts.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Goran Alković <77000136+goranalkovic-infinum@users.noreply.github.com> --- website/blog/2022-04-08-adding-fonts.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/blog/2022-04-08-adding-fonts.md b/website/blog/2022-04-08-adding-fonts.md index 7e08cfb05..06b218eb3 100644 --- a/website/blog/2022-04-08-adding-fonts.md +++ b/website/blog/2022-04-08-adding-fonts.md @@ -85,7 +85,7 @@ Run `npm start` to rebuild your **_public_** folder and assets. If you did every ### Using only one font in a block -There are multiple ways of using fonts in a block. The simplest example is if you have only one font you want to use for that specific block. In this case, we want Heading Block to only use NotoSerif. +There are multiple ways of using fonts in a block. The simplest example is if you have only one font you want to use for that specific block. In this case, we want the Heading block to only use _Noto Serif_. To make our secondary font available for use, we need to first define it as a variable. We can do that in **_/assets/styles/parts/utils/_shared-variables.scss_**. We can see there that the base font is already defined, so all we need to do is add our secondary font below. From df4a47344ca82b373a079a0242a27ccee0dfbb09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Igor=20Obradovi=C4=87?= Date: Mon, 11 Apr 2022 16:17:43 +0200 Subject: [PATCH 5/9] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Goran Alković <77000136+goranalkovic-infinum@users.noreply.github.com> --- website/blog/2022-04-08-adding-fonts.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/website/blog/2022-04-08-adding-fonts.md b/website/blog/2022-04-08-adding-fonts.md index 06b218eb3..5529d2783 100644 --- a/website/blog/2022-04-08-adding-fonts.md +++ b/website/blog/2022-04-08-adding-fonts.md @@ -102,11 +102,11 @@ After defining `--secondary-font-family` CSS variable, we can go to **_/src/Bloc font-family: var(--secondary-font-family); ``` -And that's it! The Heading Block will now use the NotoSerif font. +And that's it! The Heading block will now use the _Noto Serif_ font. ### Adding an option for selecting fonts -In some cases, you may want to give users the option to choose between fonts that they want to use in their block. For this example, we'll use the `paragraph` block where we want users to have both SourceSansPro and NotoSerif font available. +In some cases, you may want to give users the option to choose between fonts that they want to use in their block. For this example, we'll use the `paragraph` block where we want users to have both _Source Sans Pro_ and _Noto Serif_ available. First step is to add a new attribute, options and CSS variable values in **_/src/Blocks/components/paragraph/manifest.json_**: ```json From 98759928c07660806f873efec4332ac19cf19b48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Igor=20Obradovi=C4=87?= Date: Mon, 11 Apr 2022 16:59:49 +0200 Subject: [PATCH 6/9] Update content according to PR comments --- website/blog/2022-04-08-adding-fonts.md | 30 +++++++++++++------------ 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/website/blog/2022-04-08-adding-fonts.md b/website/blog/2022-04-08-adding-fonts.md index 5529d2783..97a5e88bc 100644 --- a/website/blog/2022-04-08-adding-fonts.md +++ b/website/blog/2022-04-08-adding-fonts.md @@ -11,13 +11,14 @@ hide_table_of_contents: false Every project is unique. Logo, colors, fonts, etc. are what define the visual identity of your website. In this post, we'll cover adding fonts to a project. -### Importing fonts into your project -[Our documentation](/docs/basics/fonts) covers the necessary steps to add a font to your project, but here we'll cover the process in a bit more detail. To start, we need a font (or two). For this example, I'll use **_SourceSansPro_** and **_NotoSerif_** which I've downloaded from [Google Fonts](https://fonts.google.com/). These are in the `.ttf` format, so convert them to `.woff` and `.woff2. Whatever approach you use is okay - we recommend the following tools: -- https://convertio.co/ttf-woff/ -- https://cloudconvert.com/ttf-to-woff -- https://everythingfonts.com/ttf-to-woff - -Fonts should go inside your theme's **_/assets/fonts_** folder. Copy the fonts you want to use there. You will also notice that this folder contains an **_index.js_** file. This file is used to import fonts into your project. Here's an example of how I imported my fonts: +## Importing fonts into your project +[Our documentation](/docs/basics/fonts) covers the necessary steps to add a font to your project, but here we'll cover the process in a bit more detail. To start, we need a font (or two). For this example, I'll use **_Source Sans Pro_** and **_Noto Serif_** which I've downloaded from [Google Fonts](https://fonts.google.com/). They are in the `.ttf` format (you may find some which are `.otf`, which will work in the same way), so you need to convert them to `.woff` and `.woff2`. Whatever approach you use is okay - we recommend the following tools: +- [Convertio](https://convertio.co/ttf-woff/) +- [Cloud Convert](https://cloudconvert.com/ttf-to-woff) +- [Everything Fonts](https://everythingfonts.com/ttf-to-woff) +- [Transfonter](https://transfonter.org/) + +Fonts should go inside your theme's **_/assets/fonts_** folder. Copy the fonts you want to use there. You will also notice that this folder contains an **_index.js_** file, used to import fonts into your project. Here's an example of how I imported my fonts: ```js // SourceSansPro WOFF import './SourceSansPro-Bold.woff'; @@ -73,8 +74,9 @@ Next, you can create a new file called **__typography.scss_** inside your **_/as @include font-face(global-settings(secondaryFont), 'NotoSerif-Italic', 400, italic); @include font-face(global-settings(secondaryFont), 'NotoSerif-Regular', 400); ``` +If you would like to know more about the `font-face` mixin, you can take a look at our [Sass documentation](/sass). -Because this is a new file, we have to include it. You can do that inside **_/assets/styles/parts/_shared.scss_** file: +Because this is a new file, we have to include it. You can do that inside **_/assets/styles/parts/\_shared.scss_** file: ```scss // Project specific. @import 'utils/shared-variables'; @@ -83,13 +85,13 @@ Because this is a new file, we have to include it. You can do that inside **_/as Run `npm start` to rebuild your **_public_** folder and assets. If you did everything correctly, your build should pass and you will see your fonts inside the **_public_** folder. -### Using only one font in a block +## Using only one font in a block There are multiple ways of using fonts in a block. The simplest example is if you have only one font you want to use for that specific block. In this case, we want the Heading block to only use _Noto Serif_. -To make our secondary font available for use, we need to first define it as a variable. We can do that in **_/assets/styles/parts/utils/_shared-variables.scss_**. We can see there that the base font is already defined, so all we need to do is add our secondary font below. +To make our secondary font available for use, we need to first define it as a variable. We can do that in **_/assets/styles/parts/utils/\_shared-variables.scss_**. We can see there that the base font is already defined, so all we need to do is add our secondary font below. -To make things a bit more consistent, we may also want to rename `--global-font-family` CSS variable to `--base-font-family`. Just don't forget to search/replace this new variable name across your project! Once we're done, it should look like this: +To make things a bit more consistent, we may also want to rename `--global-font-family` CSS variable to `--base-font-family`. Just don't forget to search/replace this new variable name across your project! Please note that the fallbacks for the fonts can be anything, this is just an example. Once we're done, it should look like this: ```scss --base-font-family: var(--global-base-font), -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; @@ -97,14 +99,14 @@ To make things a bit more consistent, we may also want to rename `--global-font- --secondary-font-family: var(--global-secondary-font), -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; ``` -After defining `--secondary-font-family` CSS variable, we can go to **_/src/Blocks/components/heading/heading-style.scss_** and add the following rule to the `.heading` class: +After defining the `--secondary-font-family` CSS variable, we can go to **_/src/Blocks/components/heading/heading-style.scss_** and add the following rule to the `.heading` class: ```scss font-family: var(--secondary-font-family); ``` And that's it! The Heading block will now use the _Noto Serif_ font. -### Adding an option for selecting fonts +## Adding an option for selecting fonts In some cases, you may want to give users the option to choose between fonts that they want to use in their block. For this example, we'll use the `paragraph` block where we want users to have both _Source Sans Pro_ and _Noto Serif_ available. @@ -189,7 +191,7 @@ The control for selecting a font should now be available under Paragraph options After adding this single line of CSS code, your new option for selecting fonts will now be fully functional. -### Closing thoughts +## Closing thoughts Adding fonts to a project is something you will usually only do when setting up a new project and then forget about it. As you could see in this blog post, this isn't a complicated process, but it has a specific set of steps that have to be taken in order for custom fonts to work in your project. Of course, there are other ways to include fonts in your project, but the described process is what we recommend and use. This is the (Eightshift) Way. From 998e3022732e3086b328a0bbcaf8ebfffef45147 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Igor=20Obradovi=C4=87?= Date: Tue, 12 Apr 2022 08:51:46 +0200 Subject: [PATCH 7/9] Update headings from h3 to h2 on all blog posts --- website/blog/2022-01-20-initial-setup.md | 6 ++--- .../blog/2022-01-21-components-and-blocks.md | 6 ++--- .../blog/2022-03-03-adding-blocks-wpcli.md | 10 ++++----- website/blog/2022-03-04-modifying-blocks.md | 22 +++++++++---------- 4 files changed, 22 insertions(+), 22 deletions(-) diff --git a/website/blog/2022-01-20-initial-setup.md b/website/blog/2022-01-20-initial-setup.md index f347d81e6..6b7d5aa7a 100644 --- a/website/blog/2022-01-20-initial-setup.md +++ b/website/blog/2022-01-20-initial-setup.md @@ -11,7 +11,7 @@ As is often the case when trying out something new, you might encounter some hic If you haven't already, be sure to read our official [Eightshift Docs](https://infinum.github.io/eightshift-docs/docs/welcome). -### Setup +## Setup To create Eightshift theme, navigate to `wp-content/themes` in your project and type the following in the terminal: @@ -35,7 +35,7 @@ OK, you went through the process, filled out all required information, but the t Congratulations, you've set up your Eightshift theme! -### Getting to know Eightshift dev tools +## Getting to know Eightshift dev tools After successfully setting up the theme and going through files, you'll notice this file structure is quite different from traditional WordPress themes and you may think to yourself: "Oh wow, what did I get myself into?" @@ -47,7 +47,7 @@ The final tip in this post is related to troubleshooting. Maybe you tried to add > Have you tried `composer dump-autoload` and re-running `npm start`? -### What's next in store? +## What's next in store? That's all for this post. In future posts we'll go through some more how-to examples like: - the difference between components and blocks diff --git a/website/blog/2022-01-21-components-and-blocks.md b/website/blog/2022-01-21-components-and-blocks.md index 6d592971a..a56be21a8 100644 --- a/website/blog/2022-01-21-components-and-blocks.md +++ b/website/blog/2022-01-21-components-and-blocks.md @@ -11,7 +11,7 @@ In this blog post, we'll give you a practical explanation about the difference b One of the things that is really confusing to newcomers is the difference between components and blocks. Let's break it all down. -### Component +## Component > A component is like a blank slate, a template without context. @@ -43,7 +43,7 @@ These attributes give you the option to modify the look of the component, so thi You can even add conditional logic to your options, e.g. to have the option for `imageWidth` visible only when `imagePosition` is set to left or right. And when `imagePosition` is set to top or bottom, it defaults to 100% width. -### Block +## Block So, what about blocks? Blocks can consist of one or more components and, most importantly, allow you to use them in the editor. Technically, blocks can consist of zero components, but we encourage you to build blocks from components because that increases the reusability. @@ -57,6 +57,6 @@ To do that, we'll add a new attribute called `featuredPosts` which will define w You may be wondering, can you have a block that allows you to use all options of the `card-simple` component? Of course! You can create a block that allows you to set all available options in the editor and manually add content to the image and heading. There are also block variations, which allow you to set up predefined attributes for a block. More about setting up block variations may be covered in one of the future posts. -### Conclusion +## Conclusion Hopefully, these examples helped you get a better understanding of the difference between components and blocks. It may take a bit more time or practical use to understand the difference and reasoning behind it. Our next post will walk you through downloading one of our components and blocks with WP CLI and modifying it. diff --git a/website/blog/2022-03-03-adding-blocks-wpcli.md b/website/blog/2022-03-03-adding-blocks-wpcli.md index ef45308df..bfcb6cf02 100644 --- a/website/blog/2022-03-03-adding-blocks-wpcli.md +++ b/website/blog/2022-03-03-adding-blocks-wpcli.md @@ -12,17 +12,17 @@ Although there are a few basic blocks available after creating a project, there These can be used out-of-the-box, but also as a good starting point if you need similar blocks in your projects. It will also speed up your development time since you don't have to build everything from scratch. -### Storybook +## Storybook Storybook allows you to preview how the components and blocks look and which options they have available. Since Storybook is interactive, you can try out most of the options. Think of it as a catalog with all custom blocks we've built and made ready for public use. Each entry in Storybook should have documentation that explains the block in more detail, along with implementation instructions. Before using any block, be sure to check `Dependencies` section. Although `Implementation` section lists all the necessary WP-CLI commands required to use a specific block or a component, it is recommended to check if you have the required dependencies ready in your theme. -### WP-CLI commands +## WP-CLI commands If you've read our [Initial Setup](/blog/initial-setup) post, you're already familiar with our custom WP-CLI commands. For implementing additional components, we have `wp boilerplate use_component` command. For blocks, we have `wp_boilerplate use_block` command. -### Adding new component and block in our project +## Adding new component and block in our project Let's say we need a Quote block in our project. After going through the documentation of the Quote block, we see that we have one dependency, and that is the Quote component. So, to make Quote block available in our project, we need two WP-CLI commands: @@ -35,7 +35,7 @@ You should do the commands in this order because Quote component doesn't have an The Quote block is now ready to use and available in your blocks list. You may use it as-is, or you may want to expand its functionalities with some additional attributes. More about that will be covered in the next blog post. -### Using Example block +## Using Example block If you want to build a block almost from scratch, you can use our Example block. This is a very simple block that generates all necessary files with some example options. To add an Example block to your project, use the following WP-CLI command: ```bash @@ -43,7 +43,7 @@ wp boilerplate use_block --name=example ``` Since our blocks use a predefined structure to make everything register automatically, adding Example block with WP-CLI will generate all required files. After it's added, feel free to rename the folder, as well as files with the name of your block and start modifying all the files. Simply replace "example" with the name of your block. -### Further reading +## Further reading Our documentation has all this covered in a lot more detail, so if you would like to better understand the structure of our blocks and components, here are some chapters covering these topics: diff --git a/website/blog/2022-03-04-modifying-blocks.md b/website/blog/2022-03-04-modifying-blocks.md index d38de9985..70ec1f295 100644 --- a/website/blog/2022-03-04-modifying-blocks.md +++ b/website/blog/2022-03-04-modifying-blocks.md @@ -13,12 +13,12 @@ In our previous post, we covered how to use Storybook and WP-CLI to add addition Since Eightshift Development kit is a starter theme, made for developers to jumpstart and speed up their development, you're welcome to modify files in it directly. There is no need to create a child theme to protect changes from updates. -### Modifying a block or a component? +## Modifying a block or a component? Because we used the Quote block in our previous post, we will continue using it as an example as it's a fairly simple one. One of the first questions you may ask yourself could be: "Should I modify a component or a block?". And the answer is - it depends. If you compare **_components/quote/quote.php_** (component) and **_custom/quote/quote.php_** (block), you'll notice that most of the HTML code is inside the component, while the block pretty much only renders the Quote component inside a wrapper. This example will walk you through the whole process of adding a new attribute and its options to a block. -### What will we do? +## What will we do? We want to style the block and add a new feature. An option to choose a color theme for the Quote block. These are the specs: - each Quote block has a background with rounded corners @@ -29,7 +29,7 @@ We want to style the block and add a new feature. An option to choose a color th To better help you visualize, this is how the Quote block should look like after making these changes, showcasing all three color theme variations: ![Color Theme Examples](/img/blog/color-theme-examples.png) -### Adding background +## Adding background Initial background styling is fairly straightforward. Navigate to **_src/Blocks/components/quote/quote-style.scss_** and paste the following code inside `.quote` class: @@ -45,7 +45,7 @@ For now, we will add a simple light grey background to see how it looks. We'll r You'll notice that the changes are visible both in the editor and on the frontend. Since the Gutenberg editor adds some additional markup, sometimes you'll need to add additional styling only for the editor. In case we need to override something in the editor for our Quote component, we would simply create **_quote-editor.scss_**. -### Adding new colors to your project +## Adding new colors to your project Because the theme currently doesn't have all the required colors, we need to add additional colors which will be used for the color theme feature. We will use the colors already defined in the manifest for icon color, but we need to add lighter variations of those colors to use them for the background. Navigate to your global manifest, which is located inside **_src/Blocks/manifest.json_** and add the following values inside `colors`: ```json @@ -66,7 +66,7 @@ Because the theme currently doesn't have all the required colors, we need to add } ``` -### Adding a new attribute and options to manifest +## Adding a new attribute and options to manifest For editors to be able to choose which color theme to use for the Quote block, we need to define an attribute for it in the manifest. Navigate to **_src/Blocks/components/quote/manifest.json_** and add the following value inside `attributes`: @@ -90,7 +90,7 @@ After that, since we want to have a fixed number of options, we need to define a } ``` -### CSS variables +## CSS variables Our next step is to add CSS variables to the Quote component's manifest. Inside **_manifest.json_**, on the same level as `attributes`, add the following code: ```json @@ -139,7 +139,7 @@ As you can see, the variable name is the same one we used when defining backgrou } ``` -### Outputting CSS variables in editor +## Outputting CSS variables in editor To make our color theme visible in editor, we have to add few lines of code to **_src/Blocks/components/quote/components/quote-editor.js_** file. First, we need to import a few functions. We need `useMemo` from **_react_**, `outputCssVariables` and `getUnique` from **_@eightshift/frontend-libs/scripts_** and finally, we need data from the global manifest. After importing these and defining a unique constant, your code should look like this: @@ -171,7 +171,7 @@ return ( If you try adding a Quote block in the editor, you should notice that it now has a light blue background with a quote icon in a darker shade of blue. This is the default value for the `quoteColorTheme` attribute we added in the component's manifest. -### Outputting CSS variables in the PHP template +## Outputting CSS variables in the PHP template The PHP template for the Quote component is located in **_src/Blocks/components/quote/quote.php_**. This process is similar to the one described above, it's just written in PHP. All helper methods we need for this are contained inside the `Components` class, which is already included in this file. Similar to the JS template, we need a unique value, assign it to `data-id`, and output CSS variables. After adding these, the code should look like this: @@ -195,7 +195,7 @@ $unique = Components::getUnique(); > Both PHP and JS have the same helpers to make writing code for editor and front view as similar as possible. -### Adding options +## Adding options After adding these snippets, you should already see that your block is using the blue color theme, which we defined as the default value for `quoteColorTheme` in the manifest. We want to have an easy way to change the color theme in the editor. Now we'll add a new option which will do just that. We will add these options in **_src/Blocks/components/quote/components/quote-options.js_**. Again, we will start with the imports we will need. First one is `__` from **_@wordpress/i18n_** package. Additional imports we need are from **_@eightshift/frontend-libs/scripts_**, so we will just add those to the list. @@ -251,7 +251,7 @@ The Color Theme option should now be visible and fully functional inside the Quo ![Color Theme Options](/img/blog/color-theme-options.png) -### Adding transitions in the editor +## Adding transitions in the editor The options work, but you may notice there is no transition in the editor. It is not necessary but will improve the user experience. Since we do not need transition effects on the frontend, we can add these CSS rules only to the editor. To do that, we start by creating **_quote-editor.scss_** file inside **_src/Blocks/components/quote_** folder. @@ -270,7 +270,7 @@ Because we've added a new file, we have to run `npm start` again. Now the transi ![Color Theme Change](/img/blog/color-theme-change.gif) -### Closing thoughts +## Closing thoughts In this post, we've covered the whole process of adding a new attribute. It involves a lot of steps and things to keep in mind, but once you get used to it, you'll be able to add quite powerful features to your blocks. From e6e27683db36e8f289973f49dc2f0aafc30133b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Igor=20Obradovi=C4=87?= Date: Tue, 12 Apr 2022 13:03:06 +0200 Subject: [PATCH 8/9] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Goran Alković <77000136+goranalkovic-infinum@users.noreply.github.com> --- website/blog/2022-04-08-adding-fonts.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/website/blog/2022-04-08-adding-fonts.md b/website/blog/2022-04-08-adding-fonts.md index 97a5e88bc..1619eb749 100644 --- a/website/blog/2022-04-08-adding-fonts.md +++ b/website/blog/2022-04-08-adding-fonts.md @@ -87,9 +87,9 @@ Run `npm start` to rebuild your **_public_** folder and assets. If you did every ## Using only one font in a block -There are multiple ways of using fonts in a block. The simplest example is if you have only one font you want to use for that specific block. In this case, we want the Heading block to only use _Noto Serif_. +There are multiple ways of using fonts in a block. The simplest use case is if you have only one font you want to use for that specific block. In this case, we want the Heading block to only use _Noto Serif_. -To make our secondary font available for use, we need to first define it as a variable. We can do that in **_/assets/styles/parts/utils/\_shared-variables.scss_**. We can see there that the base font is already defined, so all we need to do is add our secondary font below. +To make our secondary font available for use, we need to first define it as a CSS variable. We can do that in **_/assets/styles/parts/utils/\_shared-variables.scss_**. The base font is already defined, so all we need to do is add our secondary font definition below. To make things a bit more consistent, we may also want to rename `--global-font-family` CSS variable to `--base-font-family`. Just don't forget to search/replace this new variable name across your project! Please note that the fallbacks for the fonts can be anything, this is just an example. Once we're done, it should look like this: ```scss @@ -106,7 +106,7 @@ After defining the `--secondary-font-family` CSS variable, we can go to **_/src/ And that's it! The Heading block will now use the _Noto Serif_ font. -## Adding an option for selecting fonts +## Adding a font picker In some cases, you may want to give users the option to choose between fonts that they want to use in their block. For this example, we'll use the `paragraph` block where we want users to have both _Source Sans Pro_ and _Noto Serif_ available. @@ -136,7 +136,7 @@ First step is to add a new attribute, options and CSS variable values in **_/src } ``` -After defining a new attribute and options for the font family, we now have to add a variable to **_manifest.json_**. We can add it to the `variables` object. This approach is slightly different from the one explained in the [Modifying blocks](/blog/modifying-blocks) blog post. Here we can use `%value%` wildcard to dynamically add the selected value to our CSS variable. +After defining the new attribute and options for the font family, we now have to add a variable to **_manifest.json_**. We can add it to the `variables` object. This approach is slightly different from the one explained in the [Modifying blocks](/blog/modifying-blocks) blog post. Here we can use `%value%` wildcard to dynamically add the selected value to our CSS variable. ```json "paragraphFontFamily": [ { @@ -147,7 +147,7 @@ After defining a new attribute and options for the font family, we now have to a ] ``` -The next step is to go to **_/src/Blocks/components/paragraph/components/paragraph-options.js_** and add a control for the new font family option. The first thing we can add is a new attribute that will allow us to toggle showing the paragraph font family option on other blocks which are using the paragraph component. There might be a case where we want only one font family, so this option may come in handy in some other blocks. +The next step is to go to **_/src/Blocks/components/paragraph/components/paragraph-options.js_** and add a control for the new font family option. The first thing we can add is a new attribute that will allow us to toggle showing the Paragraph font family option on other blocks which are using the Paragraph component. There might be a case where we want only one font family, so this option may come in handy in some other blocks. ```js const { setAttributes, From 6eb1e8cfea818325dd753bea7ebe6597f75e57e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Igor=20Obradovi=C4=87?= Date: Tue, 12 Apr 2022 13:28:21 +0200 Subject: [PATCH 9/9] Add image. Content updates --- website/blog/2022-04-08-adding-fonts.md | 14 +++++++++++--- website/static/img/blog/font-picker.png | Bin 0 -> 28057 bytes 2 files changed, 11 insertions(+), 3 deletions(-) create mode 100644 website/static/img/blog/font-picker.png diff --git a/website/blog/2022-04-08-adding-fonts.md b/website/blog/2022-04-08-adding-fonts.md index 1619eb749..76a9d2137 100644 --- a/website/blog/2022-04-08-adding-fonts.md +++ b/website/blog/2022-04-08-adding-fonts.md @@ -18,6 +18,8 @@ Every project is unique. Logo, colors, fonts, etc. are what define the visual id - [Everything Fonts](https://everythingfonts.com/ttf-to-woff) - [Transfonter](https://transfonter.org/) +> Just make sure you have the proper license for the fonts you are converting. + Fonts should go inside your theme's **_/assets/fonts_** folder. Copy the fonts you want to use there. You will also notice that this folder contains an **_index.js_** file, used to import fonts into your project. Here's an example of how I imported my fonts: ```js // SourceSansPro WOFF @@ -49,6 +51,8 @@ import './NotoSerif-Italic.woff2'; import './NotoSerif-Regular.woff2'; ``` +> If you don't need to support IE11, don't include `.woff` files. This will save you some bandwidth. + To add these fonts as your base font and secondary font, go to the global manifest located in **_/src/Blocks_** and add the following inside `globalVariables`: ```json "globalVariables": { @@ -89,7 +93,7 @@ Run `npm start` to rebuild your **_public_** folder and assets. If you did every There are multiple ways of using fonts in a block. The simplest use case is if you have only one font you want to use for that specific block. In this case, we want the Heading block to only use _Noto Serif_. -To make our secondary font available for use, we need to first define it as a CSS variable. We can do that in **_/assets/styles/parts/utils/\_shared-variables.scss_**. The base font is already defined, so all we need to do is add our secondary font definition below. +To make our secondary font available for use, we need to first define it as a CSS variable. We can do that in **_/assets/styles/parts/utils/\_shared-variables.scss_**. The base font is already defined there, so all we need to do is add our secondary font definition below it. To make things a bit more consistent, we may also want to rename `--global-font-family` CSS variable to `--base-font-family`. Just don't forget to search/replace this new variable name across your project! Please note that the fallbacks for the fonts can be anything, this is just an example. Once we're done, it should look like this: ```scss @@ -136,7 +140,7 @@ First step is to add a new attribute, options and CSS variable values in **_/src } ``` -After defining the new attribute and options for the font family, we now have to add a variable to **_manifest.json_**. We can add it to the `variables` object. This approach is slightly different from the one explained in the [Modifying blocks](/blog/modifying-blocks) blog post. Here we can use `%value%` wildcard to dynamically add the selected value to our CSS variable. +After defining the new attribute and options for the font family, we now have to add a variable to **_manifest.json_**. We can add it to the `variables` object. This approach is slightly different from the one explained in the [Modifying blocks](/blog/modifying-blocks-color-theme) blog post. Here we can use `%value%` wildcard to dynamically add the selected value to our CSS variable. ```json "paragraphFontFamily": [ { @@ -180,7 +184,11 @@ Now we have to add an actual control to the options panel which will allow us to ); ``` -The control for selecting a font should now be available under Paragraph options. Saving the choice now works, but the font stays the same both in the editor and on the frontend. The final step we need to make this work is to add a CSS rule that consumes our variable to **_/src/Blocks/components/paragraph/paragraph-style.scss_**: +The control for selecting a font should now be available under Paragraph options. Saving the choice now works, but the font stays the same both in the editor and on the frontend. + +![Font Picker](/img/blog/font-picker.png) + +The final step we need to make this work is to add a CSS rule that consumes our variable to **_/src/Blocks/components/paragraph/paragraph-style.scss_**: ```scss .paragraph { // ... diff --git a/website/static/img/blog/font-picker.png b/website/static/img/blog/font-picker.png new file mode 100644 index 0000000000000000000000000000000000000000..d98127a4fb19d15736ecd5a4e16b75818aeda7cc GIT binary patch literal 28057 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