From 0385914bd945d0a045a8e93d6ff6e68778bf25ac Mon Sep 17 00:00:00 2001 From: David Itsygin Date: Fri, 8 Sep 2023 10:57:47 -0700 Subject: [PATCH] Add confetti component Co-authored-by: Paul Mayzeles <54285921+pauldanielm@users.noreply.github.com> Co-authored-by: Kevin Zhang Co-authored-by: Maximilian Medearis --- package.json | 1 + src/components/Confetti/Confetti.stories.js | 110 ++++++++++++++++++++ src/components/Confetti/Confetti.tsx | 31 ++++++ 3 files changed, 142 insertions(+) create mode 100644 src/components/Confetti/Confetti.stories.js create mode 100644 src/components/Confetti/Confetti.tsx diff --git a/package.json b/package.json index 24f816555..5f02243d8 100644 --- a/package.json +++ b/package.json @@ -66,6 +66,7 @@ "lodash.without": "^4.4.0", "memoize-one": "^5.1.1", "prop-types": "^15.7.2", + "react-confetti": "^6.1.0", "react-imask": "^6.2.2", "react-resize-detector": "^4.2.3", "react-select-plus": "1.2.0", diff --git a/src/components/Confetti/Confetti.stories.js b/src/components/Confetti/Confetti.stories.js new file mode 100644 index 000000000..267eb6fc0 --- /dev/null +++ b/src/components/Confetti/Confetti.stories.js @@ -0,0 +1,110 @@ +import { array, boolean, number } from '@storybook/addon-knobs'; +import React, { useState } from 'react'; +import Button from '../Button/Button'; +import ButtonToolbar from '../Button/ButtonToolbar'; + +import Modal from '../Modal/Modal'; +import ModalBody from '../Modal/ModalBody'; +import ModalFooter from '../Modal/ModalFooter'; +import ModalHeader from '../Modal/ModalHeader'; +import ConfettiDropper from './Confetti'; + +export default { + title: 'Confetti', + component: ConfettiDropper, + parameters: { + sourceLink: 'Modal/Modal.js', + }, +}; + +export const SimpleExample = () => { + const [open, setOpen] = useState(false); + return ( + <> + + + + setOpen(false)}>Modal title + Congrats!!!! + + + + + + + + + ); +}; + +export const HeartsExample = () => { + const [open, setOpen] = useState(false); + return ( + <> + + + { + ctx.save(); + ctx.beginPath(); + const dim = 20; + const offset = dim / 5; + ctx.moveTo(offset + 0, offset + dim / 2); + ctx.lineTo(offset + dim / 2, offset + dim); + ctx.lineTo(offset + dim, offset + dim / 2); + ctx.moveTo(offset, offset + dim / 2); + const radius = Math.sqrt((dim * dim) / 4 + (dim * dim) / 4) / 2; + ctx.arc( + offset + dim / 4, + offset + dim / 4, + radius, + (Math.PI * 3) / 4, + (Math.PI * 7) / 4 + ); + ctx.arc( + offset + (3 * dim) / 4, + offset + dim / 4, + radius, + (Math.PI * 5) / 4, + Math.PI / 4 + ); + ctx.closePath(); + ctx.fill(); + ctx.restore(); + }} + recycle={false} + /> + setOpen(false)}>Modal title + ♥♥♥♥♥♥♥♥ Congrats!!!! ♥♥♥♥♥♥♥♥ + + + + + + + + + ); +}; diff --git a/src/components/Confetti/Confetti.tsx b/src/components/Confetti/Confetti.tsx new file mode 100644 index 000000000..3918e681d --- /dev/null +++ b/src/components/Confetti/Confetti.tsx @@ -0,0 +1,31 @@ +import React, { FC, useCallback, useState } from 'react'; +import Confetti from 'react-confetti'; + +export interface ConfettiProps { + fullWidth?: boolean; +} + +const ConfettiDropper: FC = ({ + fullWidth = true, + ...props +}) => { + props = { + ...(fullWidth && { style: { position: 'fixed' }, height: window.innerHeight }), + ...props + } + const [width, setWidth] = useState(0); + + const div = useCallback((node) => { + if (node !== null) { + // set width to width of div or screen + setWidth(fullWidth ? window.innerWidth : node.getBoundingClientRect().width); + } + }, [fullWidth]); + return ( +
+ +
+ ); +}; + +export default ConfettiDropper;