mirror of
https://github.com/remvze/moodist.git
synced 2025-12-18 09:24:14 +00:00
feat: add share placeholder
This commit is contained in:
parent
85b627ecb9
commit
fe2357c995
12 changed files with 122 additions and 8 deletions
BIN
public/fonts/inter-tight-v7-latin-700.woff2
Normal file
BIN
public/fonts/inter-tight-v7-latin-700.woff2
Normal file
Binary file not shown.
|
|
@ -9,7 +9,6 @@ import { StoreConsumer } from '@/components/store-consumer';
|
||||||
import { Buttons } from '@/components/buttons';
|
import { Buttons } from '@/components/buttons';
|
||||||
import { Categories } from '@/components/categories';
|
import { Categories } from '@/components/categories';
|
||||||
import { ScrollToTop } from '@/components/scroll-to-top';
|
import { ScrollToTop } from '@/components/scroll-to-top';
|
||||||
// import { Shuffle } from '@/components/shuffle';
|
|
||||||
import { Menu } from '@/components/menu/menu';
|
import { Menu } from '@/components/menu/menu';
|
||||||
import { SnackbarProvider } from '@/contexts/snackbar';
|
import { SnackbarProvider } from '@/contexts/snackbar';
|
||||||
|
|
||||||
|
|
@ -62,7 +61,6 @@ export function App() {
|
||||||
|
|
||||||
<ScrollToTop />
|
<ScrollToTop />
|
||||||
<Menu />
|
<Menu />
|
||||||
{/* <Shuffle /> */}
|
|
||||||
</StoreConsumer>
|
</StoreConsumer>
|
||||||
</SnackbarProvider>
|
</SnackbarProvider>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
14
src/components/menu/buttons/button.tsx
Normal file
14
src/components/menu/buttons/button.tsx
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
import styles from '../menu.module.css';
|
||||||
|
|
||||||
|
interface ButtonProps {
|
||||||
|
children: React.ReactNode;
|
||||||
|
onClick: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Button({ children, onClick }: ButtonProps) {
|
||||||
|
return (
|
||||||
|
<button className={styles.menuItem} onClick={onClick}>
|
||||||
|
{children}
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
}
|
||||||
2
src/components/menu/buttons/index.ts
Normal file
2
src/components/menu/buttons/index.ts
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
export { ShuffleButton } from './shuffle';
|
||||||
|
export { ShareButton } from './share';
|
||||||
23
src/components/menu/buttons/share.tsx
Normal file
23
src/components/menu/buttons/share.tsx
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
import { useState } from 'react';
|
||||||
|
import { createPortal } from 'react-dom';
|
||||||
|
|
||||||
|
import { Modal } from '@/components/modal';
|
||||||
|
|
||||||
|
import { Button } from './button';
|
||||||
|
|
||||||
|
export function ShareButton() {
|
||||||
|
const [isModalOpen, setIsModalOpen] = useState(false);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Button onClick={() => setIsModalOpen(true)}>Share Sounds</Button>
|
||||||
|
|
||||||
|
{createPortal(
|
||||||
|
<Modal show={isModalOpen} onClose={() => setIsModalOpen(false)}>
|
||||||
|
<h1>Share Sounds!</h1>
|
||||||
|
</Modal>,
|
||||||
|
document.body,
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
9
src/components/menu/buttons/shuffle.tsx
Normal file
9
src/components/menu/buttons/shuffle.tsx
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
import { useSoundStore } from '@/store';
|
||||||
|
|
||||||
|
import { Button } from './button';
|
||||||
|
|
||||||
|
export function ShuffleButton() {
|
||||||
|
const shuffle = useSoundStore(state => state.shuffle);
|
||||||
|
|
||||||
|
return <Button onClick={shuffle}>Shuffle Sounds</Button>;
|
||||||
|
}
|
||||||
|
|
@ -24,6 +24,9 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
& .menu {
|
& .menu {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
row-gap: 4px;
|
||||||
width: 200px;
|
width: 200px;
|
||||||
padding: 4px;
|
padding: 4px;
|
||||||
background-color: var(--color-neutral-100);
|
background-color: var(--color-neutral-100);
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,8 @@ import {
|
||||||
FloatingFocusManager,
|
FloatingFocusManager,
|
||||||
} from '@floating-ui/react';
|
} from '@floating-ui/react';
|
||||||
|
|
||||||
import { useSoundStore } from '@/store';
|
import { ShuffleButton, ShareButton } from './buttons';
|
||||||
|
|
||||||
import { slideY, fade, mix } from '@/lib/motion';
|
import { slideY, fade, mix } from '@/lib/motion';
|
||||||
|
|
||||||
import styles from './menu.module.css';
|
import styles from './menu.module.css';
|
||||||
|
|
@ -22,8 +23,6 @@ import styles from './menu.module.css';
|
||||||
export function Menu() {
|
export function Menu() {
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
|
|
||||||
const shuffle = useSoundStore(state => state.shuffle);
|
|
||||||
|
|
||||||
const variants = mix(slideY(-20), fade());
|
const variants = mix(slideY(-20), fade());
|
||||||
|
|
||||||
const { context, floatingStyles, refs } = useFloating({
|
const { context, floatingStyles, refs } = useFloating({
|
||||||
|
|
@ -71,9 +70,8 @@ export function Menu() {
|
||||||
initial="hidden"
|
initial="hidden"
|
||||||
variants={variants}
|
variants={variants}
|
||||||
>
|
>
|
||||||
<button className={styles.menuItem} onClick={shuffle}>
|
<ShareButton />
|
||||||
Shuffle Sounds
|
<ShuffleButton />
|
||||||
</button>
|
|
||||||
</motion.div>
|
</motion.div>
|
||||||
</div>
|
</div>
|
||||||
</FloatingFocusManager>
|
</FloatingFocusManager>
|
||||||
|
|
|
||||||
1
src/components/modal/index.ts
Normal file
1
src/components/modal/index.ts
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
export { Modal } from './modal';
|
||||||
29
src/components/modal/modal.module.css
Normal file
29
src/components/modal/modal.module.css
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
.overlay {
|
||||||
|
position: fixed;
|
||||||
|
inset: 0;
|
||||||
|
z-index: 10;
|
||||||
|
background-color: rgb(9 9 11 / 40%);
|
||||||
|
backdrop-filter: blur(5px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal {
|
||||||
|
position: fixed;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
z-index: 12;
|
||||||
|
width: 100%;
|
||||||
|
max-height: 100%;
|
||||||
|
padding: 50px 0;
|
||||||
|
overflow-y: auto;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
|
||||||
|
& .content {
|
||||||
|
position: relative;
|
||||||
|
width: 90%;
|
||||||
|
max-width: 500px;
|
||||||
|
padding: 20px;
|
||||||
|
margin: 0 auto;
|
||||||
|
background-color: var(--color-neutral-100);
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
28
src/components/modal/modal.tsx
Normal file
28
src/components/modal/modal.tsx
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
import { AnimatePresence } from 'framer-motion';
|
||||||
|
|
||||||
|
import styles from './modal.module.css';
|
||||||
|
|
||||||
|
interface ModalProps {
|
||||||
|
children: React.ReactNode;
|
||||||
|
onClose: () => void;
|
||||||
|
show: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Modal({ children, onClose, show }: ModalProps) {
|
||||||
|
return (
|
||||||
|
<AnimatePresence>
|
||||||
|
{show && (
|
||||||
|
<>
|
||||||
|
<div
|
||||||
|
className={styles.overlay}
|
||||||
|
onClick={onClose}
|
||||||
|
onKeyDown={onClose}
|
||||||
|
/>
|
||||||
|
<div className={styles.modal}>
|
||||||
|
<div className={styles.content}>{children}</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</AnimatePresence>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -33,3 +33,12 @@
|
||||||
src: url('/fonts/inter-tight-v7-latin-600.woff2') format('woff2');
|
src: url('/fonts/inter-tight-v7-latin-600.woff2') format('woff2');
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* inter-tight-700 - latin */
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Inter Tight';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 700;
|
||||||
|
src: url('/fonts/inter-tight-v7-latin-700.woff2') format('woff2');
|
||||||
|
font-display: swap;
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue