-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Cookie banner / consent (#100)
* feat: add CookieBanner component * chore: add js-cookie package * feat: add darkBlue shadow mixin * feat: add cookie consent banner * refactor: put GA in separate component, only use if cookies accepted * refactor: setNoScroll affects html el instead of body * feat: add focus trap
- Loading branch information
1 parent
98ec3f9
commit c78406f
Showing
11 changed files
with
279 additions
and
24 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
.cookie-banner { | ||
display: flex; | ||
position: fixed; | ||
left: rem(12); | ||
bottom: rem(8); | ||
z-index: 100001; | ||
width: calc(100% - rem(24)); | ||
p + p { | ||
margin-top: rem(10); | ||
} | ||
a { | ||
margin: rem(-10) !important; | ||
} | ||
&__content { | ||
display: flex; | ||
flex-direction: column; | ||
gap: rem(8); | ||
align-items: flex-start; | ||
justify-content: space-between; | ||
border: 2px solid color(neon, green); | ||
border-radius: rem(20); | ||
box-shadow: shadow(darkBlue); | ||
background-color: color(dark, blue); | ||
gap: rem(32); | ||
flex-direction: column; | ||
padding: rem(12) rem(24); | ||
@include laptop { | ||
flex-direction: row; | ||
align-items: center; | ||
} | ||
} | ||
&__btns { | ||
gap: rem(12); | ||
margin-right: auto; | ||
@include tablet { | ||
margin-right: unset; | ||
} | ||
button { | ||
&:last-child { | ||
&:before { | ||
bottom: rem(16); | ||
} | ||
} | ||
} | ||
} | ||
&__text { | ||
font-size: rem(18) !important; | ||
&-sm { | ||
font-size: rem(16) !important; | ||
} | ||
&-container { | ||
flex-direction: column; | ||
gap: rem(8); | ||
} | ||
} | ||
&__overlay { | ||
display: block; | ||
content: ''; | ||
position: fixed; | ||
width: 100vw; | ||
height: 100vh; | ||
top: 0; | ||
left: 0; | ||
z-index: 100000; | ||
background: rgba(color(neutral, black), 0.5); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
'use client'; | ||
|
||
import FocusTrap from 'focus-trap-react'; | ||
import { m, useReducedMotion } from 'framer-motion'; | ||
import cookie from 'js-cookie'; | ||
import React, { useEffect } from 'react'; | ||
|
||
import linkStyles from '../../atoms/Link/Link.module.scss'; | ||
|
||
import styles from './CookieBanner.module.scss'; | ||
|
||
import Container from '@/atoms/Container'; | ||
import Link from '@/atoms/Link'; | ||
import Text from '@/atoms/Text'; | ||
import ButtonMolecule from '@/molecules/ButtonMolecule/ButtonMolecule'; | ||
import Flex from '@/molecules/Flex'; | ||
import Section from '@/molecules/Section'; | ||
import useStore from '@/store/useStore'; | ||
import { backToTop } from '@/utils/framer/animations'; | ||
import LazyAnimatePresence from '@/utils/framer/LazyAnimatePresence'; | ||
import { setNoScroll } from '@/utils/setNoScroll'; | ||
|
||
const CookieBanner = () => { | ||
const { showCookieBanner, setShowCookieBanner } = useStore(); | ||
|
||
const prefersReducedMotion = useReducedMotion() || false; | ||
|
||
useEffect(() => { | ||
const consentCookie = cookie.get('cookieConsent'); | ||
|
||
if (!consentCookie) { | ||
setShowCookieBanner(true); | ||
} | ||
}, []); | ||
useEffect(() => { | ||
setNoScroll(showCookieBanner); | ||
}, [showCookieBanner]); | ||
|
||
const handleAccept = () => { | ||
setShowCookieBanner(false); | ||
cookie.set('cookieConsent', 'accepted', { expires: 365 }); | ||
}; | ||
|
||
const handleReject = () => { | ||
setShowCookieBanner(false); | ||
cookie.set('cookieConsent', 'rejected', { expires: 365 }); | ||
}; | ||
|
||
if (!showCookieBanner) { | ||
return null; | ||
} | ||
|
||
return ( | ||
<LazyAnimatePresence> | ||
{showCookieBanner && ( | ||
<m.div | ||
className={styles['cookie-banner']} | ||
variants={backToTop(prefersReducedMotion)} | ||
initial='hidden' | ||
animate={showCookieBanner ? 'visible' : 'hidden'} | ||
exit='hidden' | ||
> | ||
<FocusTrap | ||
active={showCookieBanner} | ||
focusTrapOptions={{ | ||
initialFocus: false | ||
}} | ||
> | ||
<Section | ||
as='div' | ||
className={styles['cookie-banner__content']} | ||
> | ||
<Flex | ||
className={ | ||
styles['cookie-banner__text-container'] | ||
} | ||
> | ||
<Text className={styles['cookie-banner__text']}> | ||
Long Island Laser Tag uses cookies to | ||
improve your browsing experience. | ||
</Text> | ||
<Text | ||
size='sm' | ||
as='span' | ||
className={styles['cookie-banner__text-sm']} | ||
> | ||
Read our | ||
<Link | ||
href={`${ | ||
process.env | ||
.NEXT_PUBLIC_BASE_URL as string | ||
}/privacy-policy`} | ||
className={ | ||
linkStyles['link__rich-text'] | ||
} | ||
> | ||
Privacy Policy | ||
</Link> | ||
to learn more. | ||
</Text> | ||
</Flex> | ||
|
||
<Flex className={styles['cookie-banner__btns']}> | ||
<ButtonMolecule onClick={handleAccept}> | ||
Accept | ||
</ButtonMolecule> | ||
<ButtonMolecule | ||
variant='link' | ||
onClick={handleReject} | ||
className={styles['cookie-banner__reject']} | ||
> | ||
Reject | ||
</ButtonMolecule> | ||
</Flex> | ||
</Section> | ||
</FocusTrap> | ||
</m.div> | ||
)} | ||
<Container className={styles['cookie-banner__overlay']}></Container> | ||
</LazyAnimatePresence> | ||
); | ||
}; | ||
|
||
export default CookieBanner; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
'use client'; | ||
|
||
import cookie from 'js-cookie'; | ||
import Script from 'next/script'; | ||
import { useEffect, useState } from 'react'; | ||
|
||
import useStore from '@/store/useStore'; | ||
|
||
const GoogleScript = () => { | ||
const [cookiesAccepted, setCookiesAccepted] = useState(false); | ||
|
||
const { showCookieBanner } = useStore(); | ||
|
||
useEffect(() => { | ||
setCookiesAccepted(cookie.get('cookieConsent') === 'accepted'); | ||
}, [showCookieBanner]); | ||
|
||
return ( | ||
cookiesAccepted && ( | ||
<> | ||
<Script | ||
strategy='afterInteractive' | ||
src='https://www.googletagmanager.com/gtag/js?id=G-7Y1YQ9834N' | ||
/> | ||
<Script | ||
id='google-analytics' | ||
strategy='afterInteractive' | ||
dangerouslySetInnerHTML={{ | ||
__html: ` | ||
window.dataLayer = window.dataLayer || []; | ||
function gtag(){dataLayer.push(arguments);} | ||
gtag('js', new Date()); | ||
gtag('config', 'G-SPPSLWSVHZ'); | ||
` | ||
}} | ||
/> | ||
</> | ||
) | ||
); | ||
}; | ||
|
||
export default GoogleScript; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
import CookieBanner from './CookieBanner'; | ||
|
||
export default CookieBanner; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import { ZuSlice } from 'declarations'; | ||
|
||
export interface CookieBannerSlice { | ||
showCookieBanner: boolean; | ||
setShowCookieBanner: (arg: CookieBannerSlice['showCookieBanner']) => void; | ||
} | ||
|
||
const createCookieBannerSlice: ZuSlice<CookieBannerSlice> = ( | ||
set: (arg: () => Partial<CookieBannerSlice>) => void | ||
) => ({ | ||
showCookieBanner: false, | ||
setShowCookieBanner: (arg) => set(() => ({ showCookieBanner: arg })) | ||
}); | ||
|
||
export default createCookieBannerSlice; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,16 @@ | ||
import { create } from 'zustand'; | ||
|
||
import createCookieBannerSlice, { | ||
CookieBannerSlice | ||
} from './createCookieBannerSlice'; | ||
|
||
import createMenuSlice, { MenuSlice } from '@/store/createMenuSlice'; | ||
|
||
type StoreState = MenuSlice; | ||
type StoreState = MenuSlice & CookieBannerSlice; | ||
|
||
const useStore = create<StoreState>()((...args) => ({ | ||
...createMenuSlice(...args) | ||
...createMenuSlice(...args), | ||
...createCookieBannerSlice(...args) | ||
})); | ||
|
||
export default useStore; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters