Skip to content

Commit

Permalink
Merge pull request #62 from gorzelinski/confetti
Browse files Browse the repository at this point in the history
Add confetti after subscription confirmation
  • Loading branch information
gorzelinski authored Oct 1, 2024
2 parents edaabed + 3fbc14c commit 9c6588f
Show file tree
Hide file tree
Showing 13 changed files with 788 additions and 722 deletions.
8 changes: 6 additions & 2 deletions app/[lang]/subscription-confirmed/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { LINKS } from '@/constants'
import { getDictionary } from '@/scripts'
import { generateAlternateLinks, getMetaImage } from '@/lib'
import { openGraph, twitter } from '@/app/shared-metadata'
import { Button, H1, P, Section } from '@/design-system'
import { Confetti, H1, P, Section } from '@/design-system'

export async function generateMetadata({
params: { lang }
Expand Down Expand Up @@ -67,7 +67,11 @@ export default async function SubscriptionConfirmed({
<P size="xl" color="subtle">
{page.subscriptionConfirmed.description}
</P>
<Button>{page.subscriptionConfirmed.button}</Button>
<Confetti
start={page.subscriptionConfirmed.button.start}
stop={page.subscriptionConfirmed.button.stop}
more={page.subscriptionConfirmed.button.more}
/>
</Section>
</>
)
Expand Down
44 changes: 44 additions & 0 deletions design-system/components/confetti/__tests__/confetti.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { act, render, screen } from '@testing-library/react'
import { Confetti } from '../confetti'
import 'jest-canvas-mock'

const text = {
start: 'More confetti',
stop: "That's enough",
more: 'MORE!'
}

describe('Confetti', () => {
it('renders correctly', () => {
render(<Confetti start={text.start} stop={text.stop} more={text.more} />)

const button = screen.getByRole('button')

expect(button).toBeVisible()
expect(button).toHaveTextContent(text.start)
})

it('renders stop text after click', () => {
render(<Confetti start={text.start} stop={text.stop} more={text.more} />)

const button = screen.getByRole('button')
act(() => {
button.click()
})

expect(button).toHaveTextContent(text.stop)
})

it('renders more text after rage-clicking', () => {
render(<Confetti start={text.start} stop={text.stop} more={text.more} />)

const button = screen.getByRole('button')
for (let i = 0; i < 12; i++) {
act(() => {
button.click()
})
}

expect(button).toHaveTextContent(text.more)
})
})
41 changes: 41 additions & 0 deletions design-system/components/confetti/confetti.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
'use client'
import { useState } from 'react'
import ConfettiComponent from 'react-confetti'
import { useDocumentDimensions } from '@/hooks'
import { ConfettiProps } from './confetti.types'
import { Button } from '../../elements'

export const Confetti = ({ start, stop, more }: ConfettiProps) => {
const { width, height } = useDocumentDimensions()
const [recycle, setRecycle] = useState(false)
const [clicks, setClicks] = useState(0)
const [numberOfPieces, setNumberOfPieces] = useState(200)

return (
<>
<ConfettiComponent
width={width}
height={height}
recycle={recycle}
numberOfPieces={numberOfPieces}
colors={['#0466c8', '#47a3ff', '#ffbe0a', '#157f1f', '#c92c4e']}
/>
<Button
onClick={() => {
setRecycle(!recycle)
setClicks(clicks + 1)

if (clicks > 11) {
setNumberOfPieces(1000)
setClicks(-1)
return
}

setNumberOfPieces(200)
}}
>
{clicks > 11 ? more : recycle ? stop : start}
</Button>
</>
)
}
5 changes: 5 additions & 0 deletions design-system/components/confetti/confetti.types.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export type ConfettiProps = {
start: string
stop: string
more: string
}
1 change: 1 addition & 0 deletions design-system/components/confetti/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { Confetti } from './confetti'
1 change: 1 addition & 0 deletions design-system/components/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export {
type PreChildrenProps,
type PreProps
} from './code'
export { Confetti } from './confetti'
export { Image } from './image'
export { LanguageSwitch } from './language-switch'
export { LinkOrA } from './link-or-a'
Expand Down
1 change: 1 addition & 0 deletions design-system/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ export {
Avatar,
Callout,
Code,
Confetti,
Image,
LanguageSwitch,
LinkOrA,
Expand Down
6 changes: 5 additions & 1 deletion dictionaries/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -419,7 +419,11 @@
},
"heading": "Subscription confirmed!",
"description": "You have officially confirmed a subscription to my newsletter and are on the list. For effort, you deserve some confetti.",
"button": "More confetti 🎉"
"button": {
"start": "More confetti 🎉",
"stop": "That's enough 🎉",
"more": "MORE!"
}
},
"uses": {
"metadata": {
Expand Down
6 changes: 5 additions & 1 deletion dictionaries/pl.json
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,11 @@
},
"heading": "Subskrypcja potwierdzona!",
"description": "Oficjalnie potwierdziłeś subskrybcję mojego newslettera i jesteś na liście. Za wysiłek, zasługujesz na konfetti.",
"button": "Więcej konfetti 🎉"
"button": {
"start": "Więcej konfetti 🎉",
"stop": "Już wystarczy 🎉",
"more": "WIĘCEJ!"
}
},
"uses": {
"metadata": {
Expand Down
1 change: 1 addition & 0 deletions hooks/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ export {
type ScrollProgressSelector
} from './use-scroll-progress'
export { useTheme } from './use-theme'
export { useDocumentDimensions } from './use-window-dimensions'
29 changes: 29 additions & 0 deletions hooks/use-window-dimensions.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { useState, useEffect } from 'react'

export function useDocumentDimensions() {
const [documentDimensions, setDocumentDimensions] = useState({
width: 0,
height: 0
})

useEffect(() => {
setDocumentDimensions({
width: document.body.clientWidth,
height: document.body.clientHeight
})

const handleResize = () => {
setDocumentDimensions({
width: document.body.clientWidth,
height: document.body.clientHeight
})
}

window.addEventListener('resize', handleResize)
return () => {
window.removeEventListener('resize', handleResize)
}
}, [])

return documentDimensions
}
Loading

0 comments on commit 9c6588f

Please sign in to comment.