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.
<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
<meta name="viewport" content="initial-scale=1" /><meta name="format-detection" content="telephone=no" /><linkrel="shortcut icon"href="https://visage-design-system.prod.merch.vpsvc.com/latest/v5/all/icons/favicon.ico"/><linkrel="apple-touch-icon"sizes="152x152"href="https://visage-design-system.prod.merch.vpsvc.com/latest/v5/all/icons/apple-icon-152x152.png"/><linkrel="apple-touch-icon"sizes="120x120"href="https://visage-design-system.prod.merch.vpsvc.com/latest/v5/all/icons/apple-icon-120x120.png"/><linkrel="apple-touch-icon"sizes="76x76"href="https://visage-design-system.prod.merch.vpsvc.com/latest/v5/all/icons/apple-icon-76x76.png"/><linkrel="apple-touch-icon"sizes="60x60"href="https://visage-design-system.prod.merch.vpsvc.com/latest/v5/all/icons/apple-icon-60x60.png"/><linkrel="preload"href="https://visage-design-system.prod.merch.vpsvc.com/latest/v5/all/fonts/Graphik-Bold-Web-v2.woff2"as="font"crossorigin/><linkrel="preload"href="https://visage-design-system.prod.merch.vpsvc.com/latest/v5/all/fonts/Graphik-Medium-Web-v2.woff2"as="font"crossorigin/><linkrel="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><linkrel="stylesheet"type="text/css"href="https://visage-design-system.prod.merch.vpsvc.com/latest/v5/5.14.1/library/styles/components/core.min.css"/><linkrel="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 --><scripttype="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
<meta name="viewport" content="initial-scale=1" /><meta name="format-detection" content="telephone=no" /><linkrel="shortcut icon"href="https://visage-design-system.prod.merch.vpsvc.com/latest/v5/all/icons/favicon.ico"/><linkrel="apple-touch-icon"sizes="152x152"href="https://visage-design-system.prod.merch.vpsvc.com/latest/v5/all/icons/apple-icon-152x152.png"/><linkrel="apple-touch-icon"sizes="120x120"href="https://visage-design-system.prod.merch.vpsvc.com/latest/v5/all/icons/apple-icon-120x120.png"/><linkrel="apple-touch-icon"sizes="76x76"href="https://visage-design-system.prod.merch.vpsvc.com/latest/v5/all/icons/apple-icon-76x76.png"/><linkrel="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:
react: ">=16.8 || >=17.0"
react-dom: ">=16.8 || >=17.0"
react-helmet: ">=6.0" (not required if you are using VisageSlimProvider)
@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
<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
<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:
Load fonts and styles for the application.
Detects the user's browser information and provides styling context so that we can handle browser-specific styling needs.
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:
import * as React from 'react'import { TextButton } from '@vp/visage'function Example() {return <TextButton skin="primary">Submit</TextButton>}
GlobalLinkComponent
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 asVisageLink
,GatsbyLink
, andReactRouterLink
for clarity.
e.g. you can tell a VisageLink
to render a GatsbyLink
rather than an <a>
like this:
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 VisageLink
s 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.
import { Link as GatsbyLink } from 'gatsby'function MyApp() {return (<VisageProvider globalLinkComponent={GatsbyLink}><App /></VisageProvider>)}
With globalLinkProvider
configured, all VisageLink
s 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:
https://visage-design-system.prod.merch.vpsvc.com/latest/v5/storybook-html/5.5.0/index.html
https://visage-design-system.prod.merch.vpsvc.com/next/v5/storybook-react/5.5.1-beta.0/index.html
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