Vistaprint

Responsive System

React Visage has a responsive system that works with the screen classes and breakpoints defined by Visage, so that you can make your components adjust responsively based on those sizes and breakpoints.

It configures and exports a Responsive System generated by react-responsive-system.

(This system is only available via React. For the vanilla API, you can use our design tokens in your stylesheets to adjust your CSS based on the screen size.)

Usage

Render the ScreenClassProvider at the root of your app.

jsx
// index.tsx
import { ScreenClassProvider } from '@vp/visage'
function Root() {
return (
<ScreenClassProvider>
<App />
</ScreenClassProvider>
)
}

useScreenClass

You can useScreenClass in your components to find out the current screen size: "xs", "sm", "md", or "lg".

jsx
// some-component.tsx
import { useScreenClass, Carousel } from '@vp/visage'
const propsByScreenClass = {
xs: { slidesToShow: 1 },
sm: { slidesToShow: 2 },
md: { slidesToShow: 3 },
lg: { slidesToShow: 3 },
}
function SomeComponent() {
const screenClass = useScreenClass()
console.log(screenClass) // "xs" or "sm" or "md" or "lg"
return <Carousel {...propsByScreenClass[screenClass]} />
}

useIsScreenClassInitialized

It returns a boolean value and tells if the ScreenClassProvider is initialized on the browser or not.

By default, the useScreenClass hook returns the value "xs" until the ScreenClassProvider is initialized on the browser, and useIsScreenClassInitialized hook can be useful in this case if you are interested in the actual on-screen render value rather than the default value.

jsx
// some-component.tsx
import { useIsScreenClassInitialized, Carousel } from '@vp/visage'
function SomeComponent() {
const isScreenClassInitialized = useIsScreenClassInitialized()
console.log(isScreenClassInitialized) // initially false and then true after initialization
return <Carousel someProps />
}

responsive

You can also use the responsive function in order to make your component responsive.

jsx
// some-component.tsx
import { responsive, Carousel } from '@vp/visage'
const ResponsiveCarousel = responsive(Carousel)
function SomeComponent() {
return (
<ResponsiveCarousel
xs={{ slidesToShow: 1 }}
sm={{ slidesToShow: 2 }}
md={{ slidesToShow: 3 }}
lg={{ slidesToShow: 3 }}
/>
)
}

responsive components are based on the mobile-first pattern which means that any overrides will affect larger screen sizes as well as their own screen size. In our example, md and lg screens both need to have slidesToShow = 3. We can simply omit the lg override here and our responsive Carousel will inherit the md overrides!

jsx
// some-component.tsx
import { responsive, Carousel } from '@vp/visage'
const ResponsiveCarousel = responsive(Carousel)
function SomeComponent() {
return (
<ResponsiveCarousel
xs={{ slidesToShow: 1 }} // affects xs _and larger_
sm={{ slidesToShow: 2 }} // affects sm _and larger_
md={{ slidesToShow: 3 }} // affects md _and larger_
/>
)
}

Finally, since our responsive component is mobile-first we don't need to specify an override for xsxs is the default configuration for the component, so we can write it like this:

jsx
// some-component.tsx
import { responsive, Carousel } from '@vp/visage'
const ResponsiveCarousel = responsive(Carousel)
function SomeComponent() {
return (
<ResponsiveCarousel
slidesToShow={1}
sm={{ slidesToShow: 2 }} // affects sm _and larger_
md={{ slidesToShow: 3 }} // affects md _and larger_
/>
)
}

Adding custom screen classes

If you need to support custom screen classes, you can easily create a custom Responsive System! This is the entire source-code for our Responsive System implementation:

jsx
import { createResponsiveSystem } from 'react-responsive-system'
import { screenClassMaxWidths } from '@vp/visage'
export const {
ScreenClassProvider,
useScreenClass,
responsive,
useResponsiveProps,
} = createResponsiveSystem({
breakpoints: screenClassMaxWidths,
defaultScreenClass: 'xs',
cascadeMode: 'mobile-first',
})

Simply create a new file and name it something like responsive-system.ts and use the above implementation for reference.

Per the react-responsive-system docs, the breakpoints object is a map from screen class name to the maximum pixel-width for that screen class.

Visage's breakpoints object comes directly from the @vp/visage package and it looks like this:

javascript
const customScreenSizes = {
xs: 767, // xs = 0 - 767
sm: 1023, // sm = 768 - 1023
md: 1439, // md = 1024 - 1439
lg: Infinity, // lg = 1440 - Infinity
}

Also from the react-responsive-system docs:

Exactly one breakpoint must have a value of Infinity

Now we have all of the info required in order to customize our own Responsive System! Let's say that we want a breakpoint that's smaller than xs and we want to have another breakpoint that's larger than lg.

Our new breakpoints object should look like this:

javascript
const customScreenSizes = {
xxs: 320, // xxs = 0 - 320
xs: 767, // xs = 321 - 767
sm: 1023, // sm = 768 - 1023
md: 1439, // md = 1024 - 1439
lg: 1600, // lg = 1440 - 1600
xl: Infinity, // xl - 1601 - Infinity
}

Note that we made three changes:

  1. We added xxs = 320

  2. We changed lg from Infinity to 1600

  3. We added xl = Infinity

Here's how you could do that in code:

jsx
import { createResponsiveSystem } from 'react-responsive-system'
import { screenClassMaxWidths } from '@vp/visage'
const myCustomBreakpoints = {
...screenClassMaxWidths,
xxs: 320,
lg: 1600,
xl: Infinity,
}
export const {
ScreenClassProvider,
useScreenClass,
responsive,
useResponsiveProps,
} = createResponsiveSystem({
breakpoints: myCustomBreakpoints,
defaultScreenClass: 'xs',
cascadeMode: 'mobile-first',
})