mirror of
https://github.com/remvze/moodist.git
synced 2025-12-17 00:44:14 +00:00
feat: basic structure for share link
This commit is contained in:
parent
35e32152b1
commit
ef81f198ba
9 changed files with 131 additions and 71 deletions
9
src/components/menu/items/share.tsx
Normal file
9
src/components/menu/items/share.tsx
Normal 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>;
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
export { Share } from './share';
|
||||
|
|
@ -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,
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
@ -15,6 +15,7 @@ import {
|
|||
} from '@floating-ui/react';
|
||||
|
||||
import { ShuffleItem, ShareItem } from './items';
|
||||
import { ShareLinkModal } from '@/components/modals/share-link';
|
||||
|
||||
import { slideY, fade, mix } from '@/lib/motion';
|
||||
|
||||
|
|
@ -23,6 +24,8 @@ import styles from './menu.module.css';
|
|||
export function Menu() {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
|
||||
const [showShareLink, setShowShareLink] = useState(false);
|
||||
|
||||
const variants = mix(slideY(-20), fade());
|
||||
|
||||
const { context, floatingStyles, refs } = useFloating({
|
||||
|
|
@ -44,39 +47,46 @@ export function Menu() {
|
|||
]);
|
||||
|
||||
return (
|
||||
<div className={styles.wrapper}>
|
||||
<button
|
||||
aria-label="Menu"
|
||||
className={styles.menuButton}
|
||||
ref={refs.setReference}
|
||||
onClick={() => setIsOpen(prev => !prev)}
|
||||
{...getReferenceProps()}
|
||||
>
|
||||
{isOpen ? <IoClose /> : <IoMenu />}
|
||||
</button>
|
||||
<>
|
||||
<div className={styles.wrapper}>
|
||||
<button
|
||||
aria-label="Menu"
|
||||
className={styles.menuButton}
|
||||
ref={refs.setReference}
|
||||
onClick={() => setIsOpen(prev => !prev)}
|
||||
{...getReferenceProps()}
|
||||
>
|
||||
{isOpen ? <IoClose /> : <IoMenu />}
|
||||
</button>
|
||||
|
||||
<AnimatePresence>
|
||||
{isOpen && (
|
||||
<FloatingFocusManager context={context}>
|
||||
<div
|
||||
ref={refs.setFloating}
|
||||
style={floatingStyles}
|
||||
{...getFloatingProps()}
|
||||
>
|
||||
<motion.div
|
||||
animate="show"
|
||||
className={styles.menu}
|
||||
exit="hidden"
|
||||
initial="hidden"
|
||||
variants={variants}
|
||||
<AnimatePresence>
|
||||
{isOpen && (
|
||||
<FloatingFocusManager context={context} modal={false}>
|
||||
<div
|
||||
ref={refs.setFloating}
|
||||
style={floatingStyles}
|
||||
{...getFloatingProps()}
|
||||
>
|
||||
<ShareItem />
|
||||
<ShuffleItem />
|
||||
</motion.div>
|
||||
</div>
|
||||
</FloatingFocusManager>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
</div>
|
||||
<motion.div
|
||||
animate="show"
|
||||
className={styles.menu}
|
||||
exit="hidden"
|
||||
initial="hidden"
|
||||
variants={variants}
|
||||
>
|
||||
<ShareItem open={() => setShowShareLink(true)} />
|
||||
<ShuffleItem />
|
||||
</motion.div>
|
||||
</div>
|
||||
</FloatingFocusManager>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
</div>
|
||||
|
||||
<ShareLinkModal
|
||||
show={showShareLink}
|
||||
onClose={() => setShowShareLink(false)}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
max-height: 100%;
|
||||
padding: 50px 0;
|
||||
overflow-y: auto;
|
||||
pointer-events: none;
|
||||
transform: translate(-50%, -50%);
|
||||
|
||||
& .content {
|
||||
|
|
@ -22,8 +23,27 @@
|
|||
width: 90%;
|
||||
max-width: 500px;
|
||||
padding: 20px;
|
||||
padding-top: 40px;
|
||||
margin: 0 auto;
|
||||
pointer-events: fill;
|
||||
background-color: var(--color-neutral-100);
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { AnimatePresence } from 'framer-motion';
|
||||
import { IoClose } from 'react-icons/io5/index';
|
||||
|
||||
import styles from './modal.module.css';
|
||||
|
||||
|
|
@ -19,7 +20,13 @@ export function Modal({ children, onClose, show }: ModalProps) {
|
|||
onKeyDown={onClose}
|
||||
/>
|
||||
<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>
|
||||
</>
|
||||
)}
|
||||
|
|
|
|||
1
src/components/modals/share-link/index.ts
Normal file
1
src/components/modals/share-link/index.ts
Normal file
|
|
@ -0,0 +1 @@
|
|||
export { ShareLinkModal } from './share-link';
|
||||
|
|
@ -15,6 +15,7 @@
|
|||
align-items: center;
|
||||
width: 100%;
|
||||
height: 45px;
|
||||
padding: 4px;
|
||||
margin-top: 12px;
|
||||
background-color: var(--color-neutral-50);
|
||||
border: 1px solid var(--color-neutral-200);
|
||||
|
|
@ -23,9 +24,30 @@
|
|||
& input {
|
||||
flex-grow: 1;
|
||||
height: 100%;
|
||||
color: red;
|
||||
padding: 0 10px;
|
||||
font-size: var(--font-sm);
|
||||
color: var(--color-foreground);
|
||||
background: transparent;
|
||||
border: 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
28
src/components/modals/share-link/share-link.tsx
Normal file
28
src/components/modals/share-link/share-link.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue