FESK Pattern Library
Welcome to the FESK Pattern Library. This npm module is designed to allow consumers to easily include M&S styles and layouts through elements, components, modules and templates in their projects.
To contribute, see the guide below:
Installation and usage
To install the module:
npm install @mands/mns-fe-pattern-library
In order for the project to use the styles, include sassPath config in your build config file. For example, if you are using webpack add the following to your webpack.config.js
const patternLibrary = require('@mands/mns-fe-pattern-library');
[{
loader: 'sass-loader',
options: {
outputStyle: 'expanded',
sourceMap: true,
sourceMapContents: true,
includePaths: [patternLibrary.sassPath]
}
}]
In order for the project to use the icons, install the svg-spritemap-webpack-plugin to your project as a dev dependency and add the following to your webpack.config.js
plugins array:
const SvgSpritemapWebpackPlugin = require('svg-spritemap-webpack-plugin');
[
new SvgSpritemapWebpackPlugin('node_modules/@mands/mns-fe-pattern-library/icons/**/*.svg', {
output: {
filename: 'images/spritemap-[contenthash].svg'
}
})
]
Please consult the official docs on webpack plugins for more info on where to add plugins within the webpack configuration.
To implement specific parts of the pattern library visit FESK documentation portal for more detailed implementation information.
The work we have done this far on the Pattern Library (PL) is great, however there is much more to do to ensure our offering
is both valuable and consistent.
Data schema
Schema alignment:
We need to ensure that we are remaining consistent with the data that we require
for patterns. Some examples of where we differ are below.
In badge
we specify the appearance (background colour) by supplying a type
property:
{
"text" : "Offer",
"type" : "sale"
}
However, to specify the background colour for the banner
, a backgroundColor
property needs to be supplied:
{
"title": "She's is going to love this...",
"description": "From super-soft cashmere to cosy slippers, these are the perfect gifts for the women in your life",
"textColor": "black",
"backgroundColor": "white",
"images": {
"left": "http://asset2.cxnmarksandspencer.com/is/image/mands/148b4d21bbe0a3aaed9d297bf785ffce56fd239d",
"right": "http://asset2.cxnmarksandspencer.com/is/image/mands/8cbc86494cd3acbb760af273ce5debf4e340e721"
},
"link": {
"text": "Gifts, this way",
"url": "/"
}
}
The above are two very distinctly different methods for styling patterns. One allows the consumer to know exactly how an
element will look, and the other is an abstraction, and requires knowledge of what this abstraction maps to:
offer -> #C4201D
Would consumers know about this? Do we prefer the abstraction, or the specificity? With the specificity, will the
consumer manually look it up in the PL, and copy it into some data that gets persisted in a Content API?
From the above it is clear that we currently offer a variety of ways to customise the appearance of patterns. Ideally,
we should settle on a single way of doing this.
In certain cases, our desired data model might not match the data available to
consumers. Therefore, we must either:
- provide API wrappers to reach desired schema
- request APIs that returned desired schema
Style guide usage
The style guide is purely a SASS library to provide global styling for:
- accessibility
- colors
- grid
- iconography
- normalization
- typography
- utilities
These are all located in lib/mns-fe-styles
and as lib is set as a sass path you can @import
parts of this using mns-fe-styles
as the first part of the path. e.g @import 'mns-fe-styles/colors'
. You can also import everything using @import 'mns-fe-styles/all'
. It is important that you only import parts of the style guide styles once in your application otherwise you will get duplication in your CSS output.
Breakpoints
Breakpoints create an abstraction for adding responsiveness to the pattern. For example media queries such as:
@media (min-width: 768px) {
.button {
float: left;
width: 30%;
}
}
should be written in the following way:
@import 'mns-fe-styles/breakpoint';
@include media-breakpoint-up(md) {
.button {
float: left;
width: 30%;
}
}
This approach allows us to not only standardise breakpoints (with variables we are limited to 3: sm
for mobile devices, md
for tablets and lg
for desktop), but also the way @media
queries are written.
Colours
Hexadecimal colour values should not be hardcoded in CSS. Use colour variables defined in M&S palette instead.
With this approach, styling might have been written as:
.product-list__product {
color: #333;
}
and should become:
.product-list__product {
color: $color__brand--dark-grey;
}
Responsive grid
Every time we want to create a grid-based layout we should be utilising the same approach. Shared responsive grid is designed to standardise implementation.
Consider markup provided below:
<ul class="product-list">
<li class="product-list__product">...</li>
<li class="product-list__product">...</li>
<li class="product-list__product">...</li>
</ul>
One of the ways to implement three column grid would be:
.product-list__product {
float: left;
width: 30%;
}
or:
.product-list {
display: flex;
flex-wrap: wrap;
}
.product-list__product {
width: 30%;
}
As you can see you can achieve the same behaviour in a number of ways. This will create an inconsistency within codebase and will potentially lead to the same functionality being implemented more than once.
Style guide offers a single standardised approach:
@import 'mns-fe-styles/grid';
and in the markup:
<ul class="product-list">
<li class="product-list__product col-sm-12 col-md-6 col-lg-4">...</li>
<li class="product-list__product col-sm-12 col-md-6 col-lg-4">...</li>
<li class="product-list__product col-sm-12 col-md-6 col-lg-4">...</li>
</ul>
Our grid is based on 12 column Bootstrap implementation with classes above representing the following:
- col-sm-12 - represents a single (12/1) column on mobile;
- col-md-6 - represents two (12/2) columns on tablet;
- col-lg-4 - represents three (12/3) columns on desktop;
Iconography
Iconography contains all of the M&S icons available to you. Rather than needing to add an SVG to each of the projects you can simply import them alongside corresponding CSS class abstractions via:
@import 'mns-fe-styles/iconography';
Typography
Specifies look and feel for common elements such as headers or paragraphs. In addition, it provides access to M&S specific fonts.
Major Version Upgrades
Whilst we endeavour to deploy frequent, atomised updates to the Pattern Library, it is sometimes necessary (when updates have a large amount of interdependence) to bundle large releases. In these cases they will have some breaking elements by nature, as such you will need to follow the steps outlined here to ensure you are both:
- aligned to the new PL release; and
- recovered from any breaking changes that affect you.
This is likely to be substantial work, but is both mandatory and necessary for us to stay up-to-date and aligned with design.
Upgrading the Version
In the package.json
, specify the version you want to update to (within the dependencies section):
"@mands/mns-fe-pattern-library": "8.0.0",
Perform an install of all node modules the project is dependent on:
npm i
This will update the Pattern Library package to the version you have specified.
Addressing Breaking Changes
The Latest Version's CHANGELOG
After the above has been performed, you will need to run any visual and regression testing you have in place, fixing any discrepancies you find.
You will also need to perform manual testing of your app to ensure the same.
Documents
Within PL we need to ensure the data schemas are understandable, and it is clear what information needs to
be passed in, and why. There are certain thing in our current schemas that are not abundantly clear what their purpose
is. Take a look at the below schema, taken from shopping-tiles
pattern:
{
"columns": 3,
"tiles": [
{
"title": "Free delivery",
"icon": "delivery-sdd",
"description": "Free home delivery when you spend over £50",
"linkText": "Delivery options",
"url": "http://www.marksandspencer.com/s/delivery-and-collection#a"
},
{
"title": "Free store collection",
"icon": "delivery-store",
"description": "Deliver your parcel to your nearest store",
"linkText": "Collect in store",
"url": "http://www.marksandspencer.com/s/delivery-and-collection#b"
},
{
"title": "Free returns",
"icon": "delivery-sdd",
"description": "Free returns within 35 days by post, store or locker",
"linkText": "Returns & refunds",
"url": "http://www.marksandspencer.com/s/delivery-and-collection#c"
}
]
}
What does the columns
property mean, is it simply a count of the number of tiles
?
A more descriptive name might mitigate this, or alternatively, we might want some accompanying documentation to describe
what this property mean in the data.
Users
An extremely important aspect to consider with the PL is "how do people want to use it?". We need to
understand how UX/designers envisage using PL, and if there is anything we can do to help make that a reality.
Atomic design
Patterns should follow atomic design princples. For example of the page split please see PLP page breakdown.
Patterns as standalone entities
Any pattern in the pattern library can be used anywhere and because of this should make no assumptions about context.
Pattern styling and markup should be completely self contained and import all dependencies they need.
Reusability
Patterns should be created only if they are reusable (please consult with your UX/design for advice). More complex patterns containing various UI sections should be internally split for ease of understanding.
Groupings
As the pattern library grows we need to make sure we are grouping the patterns sensibly. We have chosen to group by function, there may or may not be much code similarity between the patterns but in terms of navigation it makes more sense. Examples of this could be:
-
Tiles
- Promo tiles
- Shopping tiles
- Style and living tiles
-
Lists
- Product list
- Style and living list
-
Banners...
As you can see this generally follows naming as well.
How to Add a New Font or Variant to the Pattern Library
Adding a New Font
File Structure
Inside typography/module/fonts
, add the appropriate folder, e.g. /mns-new
.
Within this folder you will need the following file structure (assuming we are adding a font called mns-new
, with two variants regular
and semibold
):
_module_mns-new.scss
-variables-local.scss
_variables.scss
MnsNew-Regular.eot
MnsNew-Regular.woff
MnsNew-Regular.woff2
MnsNew-Semibold.eot
MnsNew-Semibold.woff
MnsNew-Semibold.woff2
Populating the Files
In order to setup variants of the font you have added for use, you will need to use a the provided font-face
mixin within the module_mns-new.scss
file. For example, given we have 2 variants of this new font, the file should look like:
Font-Face Mixins
@import 'mns-fe-styles/typography/module/mixins';
@import 'mns-fe-styles/typography/module/variables';
@include font-face($mns-new-font-name, $mns-new-font-path + '/MnsNew-Variant1', woff2 woff eot, $font-weight__regular, normal);
@include font-face($mns-new-font-name, $mns-new-font-path + '/MnsLondon-Semibold', woff2 woff eot, $font-weight__semibold, normal);
The important things to note here are:
- the second argument of the mixin, which denotes the file names to be expected for the variant, these must match the files added (minus the extensions)
- the third argument, which is a list of the file extensions it will append to the file name, the order is critical here so make sure it is like above.
- the final 3 optional arguments (or 2) which denote
font-weight
, font-style
and font-stretch
.
Local Variables
The next step is to setup the _variables-local.scss
file, which should look like below:
$mns-new-font-path: 'mns-fe-styles/typography/module/fonts/mns-new' !default;
$mns-new-font-name: 'mns-new';
$font__mns-new: $mns-new-font-name, Helvetica, Arial, sans-serif;
Absolute Variables
Then the _variables.scss
file which should look like below:
$mns-new-font-path: '~@mands/mns-fe-pattern-library/lib/mns-fe-styles/typography/module/fonts/mns-new' !default;
$mns-new-font-name: 'mns-new';
$font__mns-new: $mns-new-font-name, Helvetica, Arial, sans-serif;
Surfacing the New Font in the Pattern Library
In order to be able to show this font within the pattern library, we need to add appropriate classes for its variants in the root of the typography
folder. Do this in style.scss
by adding the classes, like below:
.mns-new-font-regular {
font-family: $font__mns-new;
font-weight: $font-weight__regular;
}
.mns-new-font-semibold {
font-family: $font__mns-new;
font-weight: $font-weight__semibold;
}
The key thing with the above, is to include all valiues for font-weight
, font-style
and font-stretch
that make the font unique. In this example, as the font-style
is the same across both and only font-weight
determines the variant, we only need to include that.
If we were to include an italicised, regular weight variant, we would need to include the font-style
.
Finally, you need to add a section within the markup.hbs
file, to display an example usage of the font:
<h3>Regular</h3>
<div class="mns-new-font-regular">MNS New Regular<div>
<pre><code class="hljs">font-weight: $font-weight__regular<code></pre>
<h3>Semibold</h3>
<div class="mns-new-font-semibold">MNS New Semibold</div>
<pre><code class="hljs">font-weight: $font-semibold;<code><pre>
Adding a New Variant Only
If you want to only add a new variant to a pre-existing font, you only need to take the following steps:
- Add the font-face mixin to the relevant
module_mns-new.scss
file. - Surface the new font within the pattern library
Contacts
Development
To work on the Pattern Library and to create, update or develop patterns we provide details of our recommended setup
and in the Pattern Library README and the CONTRIBUTING guidelines.
Web Accessibility
Web accessibility is the effort to remove barriers our customers can encounter while interacting with pages we build. As the population grows older this will become more and more important. In addition to good publicity or profits, accessibility brings something completely unique, it is:
- in tune with our core values
- socially responsible
- somewhere we, as engineers, can make a lot of difference
We aim to meet the WCAG 2.0 specification, details can be found on the W3C Recommendation website. W3C also provides guides on accessibility fundamentals which will help you understand what to consider when developing for accesibility.
Some of our libraries have tests in place to validate accessibility standards, notably WCAG and W3C standards. These will capture some accessibility validations, but it is not exhaustive. Some accessbility guidelines are up to developers to adhere to and should be discussed as part of the peer review process.