theme-ui#useThemeUI JavaScript Examples

The following examples show how to use theme-ui#useThemeUI. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: invert-wrapper.jsx    From MDXP with MIT License 6 votes vote down vote up
InvertWrapper = ({children}) => {
  const {theme} = useThemeUI();

  return (
    <ThemeProvider theme={{colors: {background: theme.colors.text, text: theme.colors.background}}}>
      {children}
    </ThemeProvider>
  );
}
Example #2
Source File: image.js    From proof-of-humanity-web with MIT License 6 votes vote down vote up
Image = forwardRef((props, ref) => {
  const { theme } = useThemeUI();
  const { width, height } = theme.images?.[props.variant] ?? {};

  return props.src ? (
    <_Image ref={ref} {...props} />
  ) : (
    <ReactLoadingSkeleton
      circle={props.variant === "avatar"}
      {...props}
      width={props.width || width}
      height={props.height || height}
    />
  );
})
Example #3
Source File: flex.jsx    From MDXP with MIT License 5 votes vote down vote up
Flex = ({
  children,
  sx = {},
  variant,
  display,
  width,
  height,
  flexDirection,
  flexWrap,
  flexFlow,
  justifyContent,
  alignItems,
  alignContent,
  ...props
}) => {
  const {theme} = useThemeUI();

  // Setup variant
  let variantValue = {};
  if ((typeof variant === 'string' || variant instanceof String)) {
    variant = 'mdxp.flex.' + variant;
    variantValue = variant.split('.').reduce((acc, val) => acc?.[val], theme) || {};
  }

  if (sx.variant && (typeof sx.variant === 'string' || sx.variant instanceof String)) {
    variantValue = sx.variant.split('.').reduce((acc, val) => acc?.[val], theme) || {};
  }

  // Default values
  display = display ?? variantValue.display ?? 'flex';
  width = width ?? variantValue.width ?? '100%';

  return (
    <Block
      sx={{
        variant,
        display,
        width,
        height,
        flexDirection,
        flexWrap,
        flexFlow,
        justifyContent,
        alignItems,
        alignContent,
        ...sx
      }}
      {...props}
    >
      {children}
    </Block>
  );
}
Example #4
Source File: grid.jsx    From MDXP with MIT License 4 votes vote down vote up
Grid = ({
  children,
  sx = {},
  variant,
  display,
  width,
  height,
  grid,
  gridTemplateColumns,
  gridTemplateRows,
  gridTemplateAreas,
  gridTemplate,
  gridColumnGap,
  gridRowGap,
  gridGap,
  justifyItems,
  alignItems,
  placeItems,
  justifyContent,
  alignContent,
  placeContent,
  gridAutoColumns,
  gridAutoRows,
  gridAutoFlow,
  ...props
}) => {
  const {theme} = useThemeUI();

  // Setup variant
  let variantValue = {};
  if ((typeof variant === 'string' || variant instanceof String)) {
    variant = 'mdxp.grid.' + variant;
    variantValue = variant.split('.').reduce((acc, val) => acc?.[val], theme) || {};
  }

  if (sx.variant && (typeof sx.variant === 'string' || sx.variant instanceof String)) {
    variantValue = sx.variant.split('.').reduce((acc, val) => acc?.[val], theme) || {};
  }

  // Default values
  display = display ?? variantValue.display ?? 'grid';
  width = width ?? variantValue.width ?? '100%';
  height = height ?? variantValue.height ?? '100%';

  if (Array.isArray(gridTemplateAreas)) {
    gridTemplateAreas = '"' + gridTemplateAreas.join('" "') + '"';
  } else if (gridTemplateAreas && !gridTemplateAreas.match(/^['"].*['"]$/)) {
    gridTemplateAreas = '"' + gridTemplateAreas + '"';
  }

  return (
    <Block
      sx={{
        variant,
        display,
        width,
        height,
        grid,
        gridTemplateColumns,
        gridTemplateRows,
        gridTemplateAreas,
        gridTemplate,
        gridColumnGap,
        gridRowGap,
        gridGap,
        justifyItems,
        alignItems,
        placeItems,
        justifyContent,
        alignContent,
        placeContent,
        gridAutoColumns,
        gridAutoRows,
        gridAutoFlow,
        ...sx
      }}
      {...props}
    >
      {children}
    </Block>
  );
}
Example #5
Source File: presenter-tools.jsx    From MDXP with MIT License 4 votes vote down vote up
NavigationButtons = ({sx = {}, ...props}) => {
  const {theme} = useThemeUI();
  const color = theme?.mdxp?.presenter?.color ?? 'white';

  const deck = useDeck();
  const {next, nextSlide, previous, previousSlide, navigate} = useNavigation();

  return (
    <div
      sx={{
        variant: 'mdxp.presenter',
        display: 'flex',
        width: '100%',
        height: '100%',
        alignItems: 'center',
        justifyContent: 'center',
        overflow: 'hidden',
        '& > button': {
          width: 'auto',
          height: '75%',
          mx: '5px',
          cursor: 'hand',
          bg: 'transparent',
          border: 'none'
        },
        '& > span': {
          mx: '30px'
        },
        ...sx
      }}
      {...props}
    >
      <button
        onClick={() => navigate({slide: 0, step: 0, mode: deckModes.PRESENTER})}
        onMouseDown={e => e.preventDefault()}
      >
        <svg
          xmlns="http://www.w3.org/2000/svg"
          sx={{height: '100%', width: 'auto'}}
          width="66px" height="66px" viewBox="0 0 66 66"
          fill="none"
        >
          <circle r="30.5" transform="matrix(-1 0 0 1 33 33)" stroke={color} strokeWidth="5"/>
          <path d="M33.2078 32.8312l12.3094-6.7115v-5.8898L27.0637 30.3735v4.9789l18.4535 10.1648v-5.911l-12.3094-6.775zM20.2299 45.5172h4.0459V20.2299h-4.0459v25.2873z" fill={color}/>
        </svg>
      </button>
      <button onClick={() => previousSlide()} onMouseDown={e => e.preventDefault()}>
        <svg
          xmlns="http://www.w3.org/2000/svg"
          sx={{height: '100%', width: 'auto'}}
          width="66px" height="66px" viewBox="0 0 66 66"
          fill="none"
        >
          <circle r="30.5" transform="matrix(-1 0 0 1 33 33)" stroke={color} strokeWidth="5"/>
          <path d="M40.5412 32.8312l12.3094-6.7115v-5.8898L34.3971 30.3735v4.9789l18.4535 10.1648v-5.911l-12.3094-6.775zM20.3113 32.8312l12.3094-6.7115v-5.8898L14.1672 30.3735v4.9789l18.4535 10.1648v-5.911l-12.3094-6.775z" fill={color}/>
        </svg>
      </button>
      <button onClick={() => previous()} onMouseDown={e => e.preventDefault()}>
        <svg
          xmlns="http://www.w3.org/2000/svg"
          sx={{height: '100%', width: 'auto'}}
          width="66px" height="66px" viewBox="0 0 66 66"
          fill="none"
        >
          <circle r="30.125" transform="matrix(-1 0 0 1 32.625 32.625)" stroke={color} strokeWidth="5"/>
          <path d="M29.0805 32.4581L41.25 25.8229V20L23.0062 30.0284v4.9223L41.25 45v-5.8439l-12.1695-6.698z" fill={color} />
        </svg>
      </button>
      <span>{deck.slideIndex + 1} / {deck.slideLength}</span>
      <button onClick={() => next()} onMouseDown={e => e.preventDefault()}>
        <svg
          xmlns="http://www.w3.org/2000/svg"
          sx={{height: '100%', width: 'auto'}}
          width="66px" height="66px" viewBox="0 0 66 66"
          fill="none"
        >
          <circle cx="32.625" cy="32.625" r="30.125" stroke={color} strokeWidth="5"/>
          <path d="M36.1695 32.4581L24 25.8229V20l18.2438 10.0284v4.9223L24 45v-5.8439l12.1695-6.698z" fill={color} />
        </svg>
      </button>
      <button onClick={() => nextSlide()} onMouseDown={e => e.preventDefault()}>
        <svg
          xmlns="http://www.w3.org/2000/svg"
          sx={{height: '100%', width: 'auto'}}
          width="66px" height="66px" viewBox="0 0 66 66"
          fill="none"
        >
          <circle cx="32.625" cy="32.625" r="30.125" stroke={color} strokeWidth="5"/>
          <path d="M26.1695 32.4581L14 25.8229V20l18.2438 10.0284v4.9223L14 45v-5.8439l12.1695-6.698zm20 0L34 25.8229V20l18.2438 10.0284v4.9223L34 45v-5.8439l12.1695-6.698z" fill={color} />
        </svg>
      </button>
      <button
        onClick={() => navigate({slide: -1, step: -1, mode: deckModes.PRESENTER})}
        onMouseDown={e => e.preventDefault()}
      >
        <svg
          xmlns="http://www.w3.org/2000/svg"
          sx={{height: '100%', width: 'auto'}}
          width="66px" height="66px" viewBox="0 0 66 66"
          fill="none"
        >
          <circle cx="32.625" cy="32.625" r="30.125" stroke={color} strokeWidth="5"/>
          <path d="M32.1695 32.4581L20 25.8229V20l18.2438 10.0284v4.9223L20 45v-5.8439l12.1695-6.698zM45 45h-4V20h4v25z" fill={color} />
        </svg>
      </button>
    </div>
  );
}
Example #6
Source File: presenter-tools.jsx    From MDXP with MIT License 4 votes vote down vote up
Time = ({sx = {}, keyboardTarget, ...props}) => {
  const {theme} = useThemeUI();
  const color = theme?.mdxp?.presenter?.color || 'white';

  const [timer, setTimer] = useState(0);
  const [play, setPlay] = useState(false);
  const [datetime, setDatetime] = useState('00:00');

  useLayoutEffect(() => {
    const date = new Date();
    setDatetime(hhmmss(date.getHours(), date.getMinutes()));

    const dateUpdate = setInterval(() => {
      const date = new Date();
      setDatetime(hhmmss(date.getHours(), date.getMinutes()));
    }, 5000);
    return () => clearInterval(dateUpdate);
  }, []);

  useEffect(() => {
    if (play) {
      const timerUpdate = setInterval(() => {
        setTimer(t => t + 1);
      }, 1000);
      return () => clearInterval(timerUpdate);
    }
  }, [play]);

  const handleKeyboard = e => {
    const {metaKey, ctrlKey, altKey} = e;
    if (metaKey || ctrlKey) {
      return;
    }

    if (altKey) {
      if (e.keyCode === 84) {
        setPlay(s => !s);
      } else if (e.keyCode === 82) {
        setPlay(false);
        setTimer(0);
      }
    }
  };

  useEffect(() => {
    const currentTarget = (keyboardTarget && keyboardTarget.hasOwnProperty('current')) ? keyboardTarget.current : keyboardTarget;
    if (currentTarget) {
      currentTarget.addEventListener('keydown', handleKeyboard);
    }

    return () => {
      if (currentTarget) {
        currentTarget.removeEventListener('keydown', handleKeyboard);
      }
    };
  }, [keyboardTarget]);

  return (
    <div
      sx={{
        variant: 'mdxp.presenter',
        width: '100%',
        height: '100%',
        display: 'flex',
        flexFlow: 'column nowrap',
        justifyContent: 'flex-end',
        '&>div:first-child': {
          fontWeight: '300'
        },
        '&>div:last-child': {
          width: '100%',
          display: 'flex',
          fontSize: '2em',
          alignItems: 'baseline',
          justifyContent: 'flex-start',
          '&>button': {
            bg: 'transparent',
            border: 'none',
            cursor: 'hand',
            mx: '5px'
          },
          '& div:first-child': {
            mr: '10px'
          }
        },
        ...sx
      }}
      {...props}
    >
      <div>{datetime}</div>
      <div>
        <div>{hhmmss(...toHMS(timer), ' : ')}</div>
        <button onClick={() => setPlay(!play)} onMouseDown={e => e.preventDefault()}>
          <svg height="2em" viewBox="0 0 25 25" fill="none" xmlns="http://www.w3.org/2000/svg">
            {play ?
              (<path fillRule="evenodd" clipRule="evenodd" d="M7 25V0h3.3333v25H7zm8.6667 0V0H19v25h-3.3333z" fill={color} />) :
              (<path d="M1 23.3333V1.5702l21.7631 10.1561L1 23.3333z" stroke={color} strokeWidth="2"/>)
            }
          </svg>
        </button>
        <button
          onClick={() => {
            setPlay(false);
            setTimer(0);
          }}
          onMouseDown={e => e.preventDefault()}
        >
          <svg height="2em" viewBox="0 0 22 25" fill="none" xmlns="http://www.w3.org/2000/svg">
            <path d="M4.41177 4.41176L11.0294 0v2.94118c2.1814 0 4.3138.64686 6.1276 1.85879 1.8138 1.21192 3.2275 2.93448 4.0623 4.94984.8347 2.01539 1.0532 4.23299.6276 6.37249-.4256 2.1395-1.476 4.1048-3.0185 5.6473-1.5425 1.5424-3.5078 2.5929-5.6473 3.0185-2.1395.4255-4.3571.2071-6.37246-.6277-2.01536-.8348-3.73792-2.2484-4.94985-4.0622C.646864 18.2844 0 16.152 0 13.9706h2c0 1.7858.52957 3.5316 1.52173 5.0165.99216 1.4848 2.40237 2.6422 4.05227 3.3256 1.64991.6834 3.4654.8622 5.217.5138 1.7515-.3484 3.3604-1.2084 4.6232-2.4712 1.2628-1.2627 2.1227-2.8716 2.4711-4.6232.3484-1.7515.1696-3.567-.5138-5.2169-.6834-1.64993-1.8407-3.06013-3.3256-4.05229-1.4849-.99217-3.2306-1.52173-5.0165-1.52173v3.88235L4.41177 4.41176z" fill={color} />
          </svg>
        </button>
      </div>
    </div>
  );
}
Example #7
Source File: Header.jsx    From nextjs-prismic-blog-starter with MIT License 4 votes vote down vote up
Header = () => {
  const {theme, colorMode, setColorMode} = useThemeUI()

  return (
    <Headroom disableInlineStyles upTolerance={10} downTolerance={10}>
      <header style={{background: `${theme.colors.muted}`}} className='header'>
        <div className='header-content'>
          <div>
            <Styled.h1 style={{margin: '0'}}>
              <NextLink href='/' passHref>
                <Styled.a
                  style={{
                    textDecoration: 'none',
                    fontFamily: 'Damion',
                    letterSpacing: '0.15rem',
                  }}
                  onClick={() =>
                    trackGAEvent('logo', `clicked on site logo`, 'link click')
                  }
                  rel='noreferrer noopener'>
                  Blog
                </Styled.a>
              </NextLink>
            </Styled.h1>
          </div>
          <div className='header-links'>
            {/* <Styled.h2 style={{ margin: "0 1rem" }}>
              <Styled.a as={Link} to="/">
                Tags
              </Styled.a>
            </Styled.h2> */}
            {/* <p>
              <GoSearch
                title="Search"
                style={{
                  fontSize: "1.2rem",
                  verticalAlign: "middle",
                  marginTop: "0.2rem",
                }}
              />
            </p> */}
            <p>
              {colorMode === 'light' ? (
                <span
                  title='Switch to Dark Mode'
                  aria-label='Switch to Dark Mode'>
                  <FiSun
                    className='theme-icon'
                    onClick={() => {
                      setColorMode('dark')
                      trackGAEvent(
                        'toggle theme',
                        `enabled dark theme`,
                        'icon click'
                      )
                    }}
                  />
                </span>
              ) : (
                <span
                  title='Switch to Light Mode'
                  aria-label='Switch to Light Mode'>
                  <FiMoon
                    className='theme-icon'
                    onClick={() => {
                      setColorMode('light')
                      trackGAEvent(
                        'toggle theme',
                        `enabled light theme`,
                        'icon click'
                      )
                    }}
                  />
                </span>
              )}
            </p>
          </div>
        </div>
      </header>
    </Headroom>
  )
}
Example #8
Source File: Listing.jsx    From nextjs-prismic-blog-starter with MIT License 4 votes vote down vote up
Listing = ({articles}) => {
  const {theme} = useThemeUI()

  const GridLayout = styled.div`
    display: grid;
    grid-template-columns: repeat(auto-fit, 325px);
    grid-template-rows: auto;
    grid-gap: 1.25rem;
    justify-content: center;
    margin: auto;
    @media (max-width: ${theme.breakpoints[0]}) {
      grid-template-columns: 1fr;
    }
  `

  const ArticleCard = styled.div`
    display: grid;
    grid-template-columns: 325px;
    grid-template-rows: 200px auto;
    grid-gap: 0;
    margin: 0 auto;
    border-radius: 25px;
    box-shadow: inset -5px -5px 12px ${theme.colors.shade1},
      inset 5px 5px 12px ${theme.colors.shade2};
  `

  return (
    <GridLayout>
      {articles.map((article) => (
        <ArticleCard
          aria-label={`Read article ${article.uid}`}
          title={article.uid}
          key={article.uid}>
          <div style={{overflow: 'hidden'}}>
            <NextLink
              href={hrefResolver(article)}
              as={linkResolver(article)}
              passHref>
              <a>
                <Image
                  src={article.data.article_image.url}
                  alt={article.data.article_image.alt}
                  title={article.data.article_image.alt}
                  layout='responsive'
                  width={article.data.article_image.dimensions.width}
                  height={article.data.article_image.dimensions.height}
                  className='article-image'
                />
              </a>
            </NextLink>
          </div>
          <div
            sx={{
              px: 3,
              py: 2,

              '@media (max-width: 30rem)': {
                px: 3,
              },
            }}>
            <h2
              sx={{
                m: 0,
                pt: 0,
                minHeight: '5rem',
                fontSize: [2, 3],
                '@media (max-width: 30rem)': {
                  pt: 0,
                  height: 'auto',
                },
              }}>
              <NextLink
                href={hrefResolver(article)}
                as={linkResolver(article)}
                passHref>
                <a
                  sx={{
                    color: 'inherit',
                    textDecoration: 'none',
                    ':hover,:focus': {
                      color: 'secondary',
                      textDecoration: 'underline',
                      cursor: 'pointer',
                    },
                  }}
                  onClick={() =>
                    trackGAEvent(
                      'home',
                      `clicked on ${article.uid} article title`,
                      'text click'
                    )
                  }
                  rel='noreferrer noopener'>
                  {RichText.asText(article.data.title)}
                </a>
              </NextLink>
            </h2>
            <p
              sx={{
                my: 0,
                fontSize: [1, 2],
                height: '5.5rem',
                '@media screen and (max-width: 30rem)': {
                  height: 'auto',
                },
              }}>
              {truncateText(`${RichText.asText(article.data.excerpt)}`)}&nbsp;
              <NextLink
                href={hrefResolver(article)}
                as={linkResolver(article)}
                passHref>
                <a
                  sx={{variant: 'styles.a'}}
                  aria-label={`Read the article on ${RichText.asText(
                    article.data.title
                  )}`}
                  title={`Read the article on ${RichText.asText(
                    article.data.title
                  )}`}
                  onClick={() =>
                    trackGAEvent(
                      'home',
                      `clicked on ${article.uid} read full article`,
                      'link click'
                    )
                  }
                  rel='noreferrer noopener'>
                  Read Full Article
                </a>
              </NextLink>
            </p>
            <div
              sx={{
                display: 'flex',
                flexFlow: 'row wrap',
                justifyContent: 'flex-start',
                alignItems: 'center',
                margin: '0 auto 0 -0.25rem',
              }}>
              {article.data.categories.map(({slug}, index) => {
                return (
                  slug && (
                    <Chip
                      name={slug}
                      slug={slug}
                      type='category'
                      page='listing'
                      key={index}
                      onClick={() =>
                        trackGAEvent('home', `clicked on ${slug}`, 'chip click')
                      }
                    />
                  )
                )
              })}
            </div>
            <p
              sx={{
                fontSize: 0,
                mb: 1,
                py: 1,
              }}>
              <em
                title={`Article posted on ${formatDate(article.data.created)}`}
                aria-label={`Article posted on ${formatDate(
                  article.data.created
                )}`}>
                {formatDate(article.data.created)}
              </em>
              <span sx={{mx: 2, fontSize: '10px'}}>|</span>
              <em
                title='Time to read the article'
                aria-label='Time to read the article'>
                <FiClock style={{marginBottom: '-0.15rem'}} />
                &nbsp;{article.data.read_time}&nbsp;min read
              </em>
            </p>
          </div>
        </ArticleCard>
      ))}
    </GridLayout>
  )
}
Example #9
Source File: Code.jsx    From nextjs-prismic-blog-starter with MIT License 4 votes vote down vote up
Code = ({data: {primary}}) => {
  const {theme, colorMode} = useThemeUI()
  const [copied, setCopied] = useState(false)

  /**
   * Toast
   * language of the block copied to clipboard
   * @param {String} lang
   */
  const copyText = (lang) => {
    // remove older toast and copied state
    toast.dismiss()
    setCopied(false)

    // new toast and copied state
    toast.info(`${lang.toUpperCase()} block copied to clipboard`, {
      onOpen: () => {
        setCopied(true)
      },
      onClose: () => {
        setCopied(false)
      },
    })
  }

  const Button = styled.button`
    color: ${theme.colors.text};
    background: ${theme.colors.shade2};
    padding: 0.25rem;
    border: none;
    font-family: ${theme.fonts.body};
    letter-spacing: 1px;
    cursor: pointer;
    &:hover {
      color: ${theme.colors.accent};
      background: ${theme.colors.text};
    }
  `

  return (
    <Fragment>
      <Highlight
        {...defaultProps}
        theme={colorMode === 'light' ? light : dark}
        code={RichText.asText(primary.code)}
        language={primary.lang}>
        {({className, style, tokens, getLineProps, getTokenProps}) => (
          <pre
            className={className}
            style={{
              ...style,
              backgroundColor: theme.colors.code,
              marginLeft: primary.type === 'List' ? '2.5rem' : null,
              borderWidth: '1px',
              borderStyle: 'solid',
              borderColor: theme.colors.shade2,
              borderRadius: '0.25rem',
            }}>
            <div
              className={className}
              style={{
                ...style,
                margin: '-0.25rem auto 0.5rem auto',
                textAlign: 'right',
                color: theme.colors.accent,
                backgroundColor: theme.colors.code,
              }}>
              <span>{primary.lang.toUpperCase()}</span>
              <CopyToClipboard
                text={primary.code.text}
                onCopy={() => copyText(primary.lang)}
                style={{margin: '0 0.5rem'}}>
                {copied ? <span>Copied</span> : <Button>Copy</Button>}
              </CopyToClipboard>
            </div>
            {tokens.map((line, i) => (
              <div {...getLineProps({line, key: i})}>
                {line.map((token, key) => (
                  <span {...getTokenProps({token, key})} />
                ))}
              </div>
            ))}
          </pre>
        )}
      </Highlight>
      <ToastContainer
        autoClose={2500}
        closeOnClick
        newestOnTop
        pauseOnHover
        transition={Slide}
        draggable
        role='alert'
      />
    </Fragment>
  )
}
Example #10
Source File: Gallery.jsx    From nextjs-prismic-blog-starter with MIT License 4 votes vote down vote up
Gallery = ({data: {items}}) => {
  const [modalIsOpen, setModalIsOpen] = useState(false)
  const {theme} = useThemeUI()
  const toggleModal = () => {
    setModalIsOpen(!modalIsOpen)
  }

  const images = items.map(({image}) => {
    return {
      caption: image.alt,
      alt: image.alt,
      source: image.url,
    }
  })

  const navigationStyle = {
    backgroundColor: theme.colors.highlight,
    color: theme.colors.text,
    ':hover': {
      backgroundColor: theme.colors.gray,
    },
  }
  const galleryStyles = {
    header: (base, state) => ({
      ...base,
      padding: 20,
    }),
    navigationPrev: (base) => ({
      ...base,
      ...navigationStyle,
    }),
    navigationNext: (base) => ({
      ...base,
      ...navigationStyle,
    }),
    view: () => ({
      height: 'auto',
      width: '100%',
      margin: '0 auto -1rem auto',
      backgroundColor: theme.colors.accent,
    }),
    footer: (base, state) => {
      const opacity = state.interactionIsIdle ? 0 : 1
      const transition = 'opacity 300ms'

      return {
        ...base,
        opacity,
        transition,
        fontFamily: theme.fonts.body,
        fontSize: theme.fontSizes[(3, 4)],
      }
    },
  }

  return (
    <Fragment>
      <ModalGateway>
        {modalIsOpen ? (
          <Modal onClose={toggleModal}>
            <Carousel views={images} styles={galleryStyles} />
          </Modal>
        ) : null}
      </ModalGateway>

      <div
        style={{
          position: 'relative',
          margin: '0 auto 2rem auto',
          cursor: 'pointer',
          borderRadius: '25px',
          boxShadow: `inset -5px -5px 12px ${theme.colors.shade1},
      inset 5px 5px 12px ${theme.colors.shade2}`,
          overflow: 'hidden',
        }}
        onClick={toggleModal}>
        {items && (
          <Image
            src={items[0].image.url}
            alt={items[0].image.alt}
            title={items[0].image.alt}
            layout='responsive'
            width={items[0].image.dimensions.width}
            height={items[0].image.dimensions.height}
          />
        )}
        <p
          style={{
            position: 'absolute',
            left: 0,
            right: 0,
            bottom: 15,
            display: 'flex',
            alignItems: 'center',
            justifyContent: 'center',
            color: '#fff',
            backgroundColor: 'rgba(0,0,0,0.3)',
            borderWidth: '1px',
            borderStyle: 'solid',
            borderColor: '#f7f8f9',
            borderRadius: '25px',
            width: '200px',
            height: '40px',
            padding: '0.5rem',
            margin: '0 auto 0 auto',
            cursor: 'pointer',
            zIndex: 10,
          }}
          onClick={toggleModal}>
          View Gallery
        </p>
      </div>
    </Fragment>
  )
}