Creating a full viewport component

You can create a Frontastic component that takes up the full viewport of a browser (also known as full-bleed). Let's look at an example of how to do this.

Below is an example of a hero Frontastic component. The image can either be the full width of the grid, or the full width of the viewport.

Full width of grid (12-column layout element)

Full width of viewport (full-bleed)

1 layout element example1 layout element example

Full bleed image exampleFull bleed image example

Let's build a simplified example:

As always, we start with the schema. We'll create a text field and a toggle so users of the Frontastic studioFrontastic studio - The interface you use to manage, build, and edit all areas of your project and commerce sites. Previously known as `backstage`. can turn our full-bleed image feature on and off.

{
    "tasticType": "frontastic/examples/hero",
     "name": "Hero",
     "icon": "image",
     "category": "content",
     "schema": [
        {
            "name": "Content",
            "fields": [
                {
                    "label": "Image",
                    "field": "image",
                    "type": "media"
                },
                {
                    "label": "Full-bleed?",
                    "field": "isFullBleed",
                    "type": "boolean",
                    "required": true,
                    "default": true
                },
                {
                    "label": "Aspect ratio",
                    "field": "aspect",
                    "type": "enum",
                    "default": "16/9",
                    "values": [
                        {
                            "value": "original",
                            "name": "Original"
                        },
                        {
                            "value": "16/9",
                            "name": "16:9"
                        },
                        {
                            "value": "4/3",
                            "name": "4:3"
                        },
                        {
                            "value": "21/9",
                            "name": "21:9"
                        }
                    ]
                }
            ]
        }
     ]
}

Upload this schema to the Frontastic studio.

Next, we need to create our tastic.jsx file to receive the information from the schema.

import React from 'react'
import PropTypes from 'prop-types'

import Hero from '../../../patterns/molecules/Hero'
import tastify from '@frontastic/catwalk/src/js/helper/tastify'

const HeroTastic = ({ data }) => {
    return <Hero {...data} />
}

HeroTastic.propTypes = {
    data: PropTypes.object.isRequired,
}

export default tastify({ translate: true })(HeroTastic)

Then, we create a wrapper component and add it to our layout folder. This is a simple React Component that makes sure its contents (the children) fill up the whole horizontal viewport space. To accomplish this we use a little CSS trick.

import React from 'react'
import PropTypes from 'prop-types'

export default function FullPageWidthWrapper ({ children, className = '' }) {
    return (
        <div
            className={className}
            style={{
                width: '100vw',
                position: 'relative',
                left: '50%',
                right: '50%',
                marginLeft: '-50vw',
                marginRight: '-50vw',
            }}
            >
            {children}
        </div>
    )
}
FullPageWidthWrapper.propTypes = {
    children: PropTypes.any,
    className: PropTypes.string,
}

We can now use the wrapper to wrap the contents of our component if the users of the Frontastic studioFrontastic studio - The interface you use to manage, build, and edit all areas of your project and commerce sites. Previously known as `backstage`. choose to do so using the toggle. We do this in the index.tsx of the component.

import React from 'react'
import PropTypes from 'prop-types'
import MediaImage from '@frontastic/catwalk/src/js/mediaImage'

import FullPageWidthWrapper from '../Layout/FullPageWidthWrapper'

const Hero = ({ image, aspect, isFullBleed }) => {
    const aspectClass = {
        'original': '',
        '16/9': 'pb-16/9',
        '4/3': 'pb-4/3',
        '21/9': 'pb-21/9',
    }

    const calculateAspectStyle = (aspect, img) => {
        if (aspect === 'original' && img) {
            return { paddingBottom: '${(img.media.height / img.media.width) * 100}%'}
        }
        return {}
    }

    const content = (
        <div className={'relative ${aspectClass[aspect]}'} style={{...calculateAspectStyle(aspect, image)}}>
            <MediaImage
                className={'w-${isFullBleed ? 'full' : 'auto'} absolute'}
                media={image}
            />
        </div>
    )
   
    if (isFullBleed) {
        return <FullPageWidthWrapper>{content}</FullPageWidthWrapper>
    }

    return content
}

Hero.propTypes = {
    image: PropTypes.object.isRequired,
    aspect: PropTypes.string.isRequired,
    isFullBleed: PropTypes.bool.isRequired,
}

export default Hero

And that's it. When this component is added to a page version in the Frontastic studio, you can now select the image and if it's full-bleed or not:


Did this page help you?