feat: basic structure for share link

This commit is contained in:
MAZE 2024-01-02 22:20:59 +03:30
parent 35e32152b1
commit ef81f198ba
9 changed files with 131 additions and 71 deletions

View file

@ -0,0 +1,9 @@
import { Item } from '../item';
interface ShareProps {
open: () => void;
}
export function Share({ open }: ShareProps) {
return <Item onClick={open}>Share Sounds</Item>;
}

View file

@ -1 +0,0 @@
export { Share } from './share';

View file

@ -1,36 +0,0 @@
import { useState } from 'react';
import { createPortal } from 'react-dom';
import { IoCopyOutline } from 'react-icons/io5/index';
import { Modal } from '@/components/modal';
import { Item } from '../../item';
import styles from './share.module.css';
export function Share() {
const [isModalOpen, setIsModalOpen] = useState(false);
return (
<>
<Item onClick={() => setIsModalOpen(true)}>Share Sounds</Item>
{createPortal(
<Modal show={isModalOpen} onClose={() => setIsModalOpen(false)}>
<h1 className={styles.heading}>Share your sound selection!</h1>
<p className={styles.desc}>
Copy and send the following link to the person you want to share
your selection with.
</p>
<div className={styles.inputWrapper}>
<input type="text" onFocus={e => e.stopPropagation()} />
<button>
<IoCopyOutline />
</button>
</div>
</Modal>,
document.body,
)}
</>
);
}

View file

@ -15,6 +15,7 @@ import {
} from '@floating-ui/react'; } from '@floating-ui/react';
import { ShuffleItem, ShareItem } from './items'; import { ShuffleItem, ShareItem } from './items';
import { ShareLinkModal } from '@/components/modals/share-link';
import { slideY, fade, mix } from '@/lib/motion'; import { slideY, fade, mix } from '@/lib/motion';
@ -23,6 +24,8 @@ import styles from './menu.module.css';
export function Menu() { export function Menu() {
const [isOpen, setIsOpen] = useState(false); const [isOpen, setIsOpen] = useState(false);
const [showShareLink, setShowShareLink] = useState(false);
const variants = mix(slideY(-20), fade()); const variants = mix(slideY(-20), fade());
const { context, floatingStyles, refs } = useFloating({ const { context, floatingStyles, refs } = useFloating({
@ -44,39 +47,46 @@ export function Menu() {
]); ]);
return ( return (
<div className={styles.wrapper}> <>
<button <div className={styles.wrapper}>
aria-label="Menu" <button
className={styles.menuButton} aria-label="Menu"
ref={refs.setReference} className={styles.menuButton}
onClick={() => setIsOpen(prev => !prev)} ref={refs.setReference}
{...getReferenceProps()} onClick={() => setIsOpen(prev => !prev)}
> {...getReferenceProps()}
{isOpen ? <IoClose /> : <IoMenu />} >
</button> {isOpen ? <IoClose /> : <IoMenu />}
</button>
<AnimatePresence> <AnimatePresence>
{isOpen && ( {isOpen && (
<FloatingFocusManager context={context}> <FloatingFocusManager context={context} modal={false}>
<div <div
ref={refs.setFloating} ref={refs.setFloating}
style={floatingStyles} style={floatingStyles}
{...getFloatingProps()} {...getFloatingProps()}
>
<motion.div
animate="show"
className={styles.menu}
exit="hidden"
initial="hidden"
variants={variants}
> >
<ShareItem /> <motion.div
<ShuffleItem /> animate="show"
</motion.div> className={styles.menu}
</div> exit="hidden"
</FloatingFocusManager> initial="hidden"
)} variants={variants}
</AnimatePresence> >
</div> <ShareItem open={() => setShowShareLink(true)} />
<ShuffleItem />
</motion.div>
</div>
</FloatingFocusManager>
)}
</AnimatePresence>
</div>
<ShareLinkModal
show={showShareLink}
onClose={() => setShowShareLink(false)}
/>
</>
); );
} }

View file

@ -15,6 +15,7 @@
max-height: 100%; max-height: 100%;
padding: 50px 0; padding: 50px 0;
overflow-y: auto; overflow-y: auto;
pointer-events: none;
transform: translate(-50%, -50%); transform: translate(-50%, -50%);
& .content { & .content {
@ -22,8 +23,27 @@
width: 90%; width: 90%;
max-width: 500px; max-width: 500px;
padding: 20px; padding: 20px;
padding-top: 40px;
margin: 0 auto; margin: 0 auto;
pointer-events: fill;
background-color: var(--color-neutral-100); background-color: var(--color-neutral-100);
border-radius: 8px; border-radius: 8px;
& .close {
position: absolute;
top: 10px;
right: 10px;
display: flex;
align-items: center;
justify-content: center;
width: 20px;
height: 20px;
font-size: 16px;
color: var(--color-foreground-subtle);
cursor: pointer;
background-color: transparent;
border: none;
outline: none;
}
} }
} }

View file

@ -1,4 +1,5 @@
import { AnimatePresence } from 'framer-motion'; import { AnimatePresence } from 'framer-motion';
import { IoClose } from 'react-icons/io5/index';
import styles from './modal.module.css'; import styles from './modal.module.css';
@ -19,7 +20,13 @@ export function Modal({ children, onClose, show }: ModalProps) {
onKeyDown={onClose} onKeyDown={onClose}
/> />
<div className={styles.modal}> <div className={styles.modal}>
<div className={styles.content}>{children}</div> <div className={styles.content}>
<button className={styles.close} onClick={onClose}>
<IoClose />
</button>
{children}
</div>
</div> </div>
</> </>
)} )}

View file

@ -0,0 +1 @@
export { ShareLinkModal } from './share-link';

View file

@ -15,6 +15,7 @@
align-items: center; align-items: center;
width: 100%; width: 100%;
height: 45px; height: 45px;
padding: 4px;
margin-top: 12px; margin-top: 12px;
background-color: var(--color-neutral-50); background-color: var(--color-neutral-50);
border: 1px solid var(--color-neutral-200); border: 1px solid var(--color-neutral-200);
@ -23,9 +24,30 @@
& input { & input {
flex-grow: 1; flex-grow: 1;
height: 100%; height: 100%;
color: red; padding: 0 10px;
font-size: var(--font-sm);
color: var(--color-foreground);
background: transparent; background: transparent;
border: none; border: none;
outline: none; outline: none;
} }
& button {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
aspect-ratio: 1 / 1;
color: var(--color-foreground);
cursor: pointer;
background-color: var(--color-neutral-100);
border: none;
border-radius: 4px;
outline: none;
transition: 0.2s;
&:hover {
background-color: var(--color-neutral-200);
}
}
} }

View file

@ -0,0 +1,28 @@
import { IoCopyOutline } from 'react-icons/io5/index';
import { Modal } from '@/components/modal';
import styles from './share-link.module.css';
interface ShareLinkModalProps {
onClose: () => void;
show: boolean;
}
export function ShareLinkModal({ onClose, show }: ShareLinkModalProps) {
return (
<Modal show={show} onClose={onClose}>
<h1 className={styles.heading}>Share your sound selection!</h1>
<p className={styles.desc}>
Copy and send the following link to the person you want to share your
selection with.
</p>
<div className={styles.inputWrapper}>
<input type="text" value="https://moodist.app/?share=test" />
<button>
<IoCopyOutline />
</button>
</div>
</Modal>
);
}