Vistaprint

Page Setup

What each page needs to support Visage

The <html> Tag

The html tag must have a lang attribute whose value is the language tag for that locale's language and region, using the language and region subtags. For instance, the language tag for Irish English would be en-IE, while the language tag for United States Spanish would be es-US.

markup
<html lang="en-IE">
<!--
en-IE is for Ireland and English specifically;
use the value appropriate for the user's locale and language
-->
</html>

VanillaJS Implementation

This content should go at the top of the <head> tag, right after the <title> tag -

Note: If you are using canonical domain instead of visage default domain(https://visage-design-system.prod.merch.vpsvc.com), you will need to provide additional proxy /visage after the domain.

eg. https://www.vistaprint.com/visage/latest/v5/all/icons/favicon.ico

markup
<meta name="viewport" content="initial-scale=1" />
<meta name="format-detection" content="telephone=no" />
<link
rel="shortcut icon"
href="https://visage-design-system.prod.merch.vpsvc.com/latest/v5/all/icons/favicon.ico"
/>
<link
rel="apple-touch-icon"
sizes="152x152"
href="https://visage-design-system.prod.merch.vpsvc.com/latest/v5/all/icons/apple-icon-152x152.png"
/>
<link
rel="apple-touch-icon"
sizes="120x120"
href="https://visage-design-system.prod.merch.vpsvc.com/latest/v5/all/icons/apple-icon-120x120.png"
/>
<link
rel="apple-touch-icon"
sizes="76x76"
href="https://visage-design-system.prod.merch.vpsvc.com/latest/v5/all/icons/apple-icon-76x76.png"
/>
<link
rel="apple-touch-icon"
sizes="60x60"
href="https://visage-design-system.prod.merch.vpsvc.com/latest/v5/all/icons/apple-icon-60x60.png"
/>
<link
rel="preload"
href="https://visage-design-system.prod.merch.vpsvc.com/latest/v5/all/fonts/Graphik-Bold-Web-v2.woff2"
as="font"
crossorigin
/>
<link
rel="preload"
href="https://visage-design-system.prod.merch.vpsvc.com/latest/v5/all/fonts/Graphik-Medium-Web-v2.woff2"
as="font"
crossorigin
/>
<link
rel="preload"
href="https://visage-design-system.prod.merch.vpsvc.com/latest/v5/all/fonts/Graphik-Regular-Web-v2.woff2"
as="font"
crossorigin
/>
<style>
@font-face {
font-family: "Graphik";
font-stretch: normal;
font-style: normal;
font-weight: 900;
src: url("https://visage-design-system.prod.merch.vpsvc.com/latest/v5/all/fonts/Graphik-Bold-Web-v2.woff2") format("woff2"),
url("https://visage-design-system.prod.merch.vpsvc.com/latest/v5/all/fonts/Graphik-Bold-Web-v2.woff") format("woff");
}
@font-face {
font-family: "Graphik";
font-stretch: normal;
font-style: normal;
font-weight: 700;
src: url("https://visage-design-system.prod.merch.vpsvc.com/latest/v5/all/fonts/Graphik-Medium-Web-v2.woff2") format("woff2"),
url("https://visage-design-system.prod.merch.vpsvc.com/latest/v5/all/fonts/Graphik-Medium-Web-v2.woff") format("woff");
}
@font-face {
font-family: "Graphik";
font-stretch: normal;
font-style: normal;
font-weight: 400;
src: url("https://visage-design-system.prod.merch.vpsvc.com/latest/v5/all/fonts/Graphik-Regular-Web-v2.woff2") format("woff2"),
url("https://visage-design-system.prod.merch.vpsvc.com/latest/v5/all/fonts/Graphik-Regular-Web-v2.woff") format("woff");
}
</style>
<link
rel="stylesheet"
type="text/css"
href="https://visage-design-system.prod.merch.vpsvc.com/latest/v5/5.14.1/library/styles/components/core.min.css"
/>
<link
rel="stylesheet"
type="text/css"
href="https://visage-design-system.prod.merch.vpsvc.com/latest/v5/5.14.1/library/styles/base/utilities.min.css"
/>
<meta name="theme-color" content="#006196" />
<!-- Add below script after the <body> tag -->
<script
type="text/javascript"
src="https://visage-design-system.prod.merch.vpsvc.com/latest/v5/5.14.1/vanilla-js/core.min.js"
></script>

React Implementation

In the <head> tag

This content should go at the top of the <head> tag, right after the <title> tag:

Note: If you are using canonical domain instead of visage default domain(https://visage-design-system.prod.merch.vpsvc.com), you will need to provide additional proxy /visage after the domain.

eg. https://www.vistaprint.com/visage/latest/v5/all/icons/favicon.ico

markup
<meta name="viewport" content="initial-scale=1" />
<meta name="format-detection" content="telephone=no" />
<link
rel="shortcut icon"
href="https://visage-design-system.prod.merch.vpsvc.com/latest/v5/all/icons/favicon.ico"
/>
<link
rel="apple-touch-icon"
sizes="152x152"
href="https://visage-design-system.prod.merch.vpsvc.com/latest/v5/all/icons/apple-icon-152x152.png"
/>
<link
rel="apple-touch-icon"
sizes="120x120"
href="https://visage-design-system.prod.merch.vpsvc.com/latest/v5/all/icons/apple-icon-120x120.png"
/>
<link
rel="apple-touch-icon"
sizes="76x76"
href="https://visage-design-system.prod.merch.vpsvc.com/latest/v5/all/icons/apple-icon-76x76.png"
/>
<link
rel="apple-touch-icon"
sizes="60x60"
href="https://visage-design-system.prod.merch.vpsvc.com/latest/v5/all/icons/apple-icon-60x60.png"
/>
<meta name="theme-color" content="#006196" />

Package Installation

Install the package `@vp/visage` using the command:

npm install @vp/visage

If your project isn't already configured to install packages from Vistaprint Artifactory, check out this article on Confluence.

Peer dependencies:

The package has peer dependencies on the following. Make sure to install them as well meeting the version criteria:

  1. react: ">=16.8 || >=17.0"

  2. react-dom: ">=16.8 || >=17.0"

  3. react-helmet: ">=6.0" (not required if you are using VisageSlimProvider)

  4. @vp/browserslist-config-vp: latest

SASS:

If you’re using node-sass in your project, we recommend that you use sass instead of node-sass with Visage v5. sass works with all the major bundlers and frameworks (eg. gatsby, webpack, snowpack, parcel, etc) without you needing to change anything in the configuration.

npm uninstall node-sass # if already installed

npm i sass -D

Bookends:

If your project is using Bookends, you’ll need to update Bookends, with the version that provides Visage 5 support:

npm i @vp/react-bookends@6.0.0

npm i @vp/search-react-component@2.0.0

Page basics

Pages in the new platform need a single, consistent set of HTML tags and CSS classes for wrapping major elements of the page, to provide standard layout, and to support any behaviors we want to be consistent across the site: Your individual environment may already be providing some of these tags, e.g. through VisageProvider when using the visage library. If so, do not duplicate them.

Page basics for React apps

jsx
<VisageProvider>
<SiteContent>
{/* header goes here */}
<SiteMain>
<MainContentStart /> {/* for accessibility support */}
{/* unbounded page content does not need a BoundedContent wrapper */}
<BoundedContent>
{/* bounded page content goes inside of this wrapper */}
</BoundedContent>
{/* you can have multiple unbounded sections */}
<BoundedContent>{/* and multiple bounded sections */}</BoundedContent>
</SiteMain>
{/* footer goes here */}
</SiteContent>
</VisageProvider>

Page basics for non-React apps

markup
<div class="site-content">
<!-- this tag should be the first child of the body tag -->
<!-- header goes here -->
<main class="site-main">
<span id="maincontentstart"></span>
<!-- for accessibility support -->
<!-- your page content goes here -->
</main>
<!-- footer goes here -->
</div>

React considerations

If you are using Visage with React, there are some additional considerations:

VisageProvider

Near the root of your app, you should render the VisageProvider. The VisageProvider's job is to provide global context to all Visage components. Presently, it enables the following capabilities:

  1. Load fonts and styles for the application.

  2. Detects the user's browser information and provides styling context so that we can handle browser-specific styling needs.

  3. Allows you to globally configure the component that's rendered when you use the Visage Link component.

More details about the VisageProvider and its props can be found at this link

VisageSlimProvider

It’s an alternative to VisageProvider and the difference is it doesn’t handle or concerns with the loading of styles, fonts or themes. When using this, it’s expected from the developer to handle the loading of all the stylesheets and fonts on their own and since the stylesheets loading will be handle by the user, the react-helmet package is not required by Visage.

The configuration mentioned in the page Adding the Visage files for VisageProvider is irrelevant except for the props globalLinkComponent and disableBrowserNameToDocument.

We recommend using VisageProvider over this however, it can be useful in the case of Next.js projects where using VisageProvider for loading styles involves cumbersome changes in the setup as done in our example.

Adding components

Once the styles are included, you can use Visage to import the Visage components:

jsx
import * as React from 'react'
import { TextButton } from '@vp/visage'
function Example() {
return <TextButton skin="primary">Submit</TextButton>
}

It is common in single-page apps to use a routing library like React Router in order to handle client-side routing. Frameworks like Gatsby and Next make use of a routing library as well.

One thing that routing libraries have in common is that they ship their own Link components that you must use throughout your SPA rather than simply rendering <a> tags. This allows the routing library to circumvent the browser's normal anchor logic and enables the library to handle the linking (and even pre-fetching in some cases).

All Visage components are configurable in such a way that you can easily tell them to render a custom component rather than the default tag that they usually render.

Visage, Gatsby, and React-Router all export a component with the name Link which is confusing. From here on, I'll refer to those as VisageLinkGatsbyLink, and ReactRouterLink for clarity.

e.g. you can tell a VisageLink to render a GatsbyLink rather than an <a> like this:

jsx
import { Link as VisageLink } from '@vp/visage'
import { Link as GatsbyLink } from 'gatsby'
function MyComponent() {
return (
<VisageLink component={GatsbyLink} href="#">
Navigate somewhere
</VisageLink>
)
}

But what if you want all VisageLinks to use GatsbyLink by default? It would be tedious and error-prone to add the component prop to every instance of VisageLink.

That's where globalLinkComponent comes in.

jsx
import { Link as GatsbyLink } from 'gatsby'
function MyApp() {
return (
<VisageProvider globalLinkComponent={GatsbyLink}>
<App />
</VisageProvider>
)
}

With globalLinkProvider configured, all VisageLinks underneath the VisageProvider will render a GatsbyLink by default! And don't worry, you can still override any individual VisageLink's component via the component prop.

Bounded Content

This isn't strictly required, but most pages will want to wrap most of their content in a Bounded Content component (BoundedContent component in visage) in order to provide some standardized spacing between the content and the edge of the screen. Bounded Content also provides a maximum width for your content so that it doesn't stretch too wide on super-wide screens.

Per component

The above will provide you with the Visage foundation, but many components will have additional CSS and JS dependencies. These will be listed on that component's page.

Examples

Storybook

From v5 onwards, Visage provides a storybook for each version and for both Vanilla & React implementation, so that the developers can view and explore the components in isolation and for whichever version of Visage they want (including experimental and next versions).

URL format to view a particular storybook:

https://visage-design-system.prod.merch.vpsvc.com/{releaseType}/v5/{storybookType}/{version}/index.html

releaseType -> 'latest' | 'next' | 'experimental' (Refrain from using next & experimental unless you know a particular version was released in modes like alpha, beta or experimental)

storybookType -> 'strorybook-react' | 'strorybook-html'

version -> Visage version

Valid examples include:

Frameworks

Visit the below repository to find the basic implementation of Visage (multiple major versions) for the most commonly used frameworks like Gatsby, Next.js, etc.

https://gitlab.com/vistaprint-org/merchandising-technology/visage/visage-examples