mirror of
https://github.com/remvze/moodist.git
synced 2026-03-10 14:03:14 +08:00
feat: implement basic snackbar
This commit is contained in:
@@ -8,6 +8,7 @@ import { Container } from '@/components/container';
|
||||
import { StoreConsumer } from '@/components/store-consumer';
|
||||
import { Buttons } from '@/components/buttons';
|
||||
import { Categories } from '@/components/categories';
|
||||
import { SnackbarProvider } from '@/contexts/snackbar';
|
||||
|
||||
import { sounds } from '@/data/sounds';
|
||||
|
||||
@@ -48,11 +49,13 @@ export function App() {
|
||||
}, [favoriteSounds, categories]);
|
||||
|
||||
return (
|
||||
<StoreConsumer>
|
||||
<Container>
|
||||
<Buttons />
|
||||
<Categories categories={allCategories} />
|
||||
</Container>
|
||||
</StoreConsumer>
|
||||
<SnackbarProvider>
|
||||
<StoreConsumer>
|
||||
<Container>
|
||||
<Buttons />
|
||||
<Categories categories={allCategories} />
|
||||
</Container>
|
||||
</StoreConsumer>
|
||||
</SnackbarProvider>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import { BiPause, BiPlay } from 'react-icons/bi/index';
|
||||
import { motion } from 'framer-motion';
|
||||
|
||||
import { useSoundStore } from '@/store';
|
||||
import { useSnackbar } from '@/contexts/snackbar';
|
||||
import { cn } from '@/helpers/styles';
|
||||
|
||||
import styles from './play.module.css';
|
||||
@@ -13,8 +14,10 @@ export function PlayButton() {
|
||||
const toggle = useSoundStore(state => state.togglePlay);
|
||||
const noSelected = useSoundStore(state => state.noSelected());
|
||||
|
||||
const showSnackbar = useSnackbar();
|
||||
|
||||
const handleClick = () => {
|
||||
if (noSelected) return pause();
|
||||
if (noSelected) return showSnackbar('Please first select a sound to play.');
|
||||
|
||||
toggle();
|
||||
};
|
||||
@@ -26,7 +29,6 @@ export function PlayButton() {
|
||||
return (
|
||||
<motion.button
|
||||
className={cn(styles.playButton, noSelected && styles.disabled)}
|
||||
disabled={noSelected}
|
||||
layout
|
||||
onClick={handleClick}
|
||||
>
|
||||
|
||||
1
src/components/snackbar/index.ts
Normal file
1
src/components/snackbar/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export { Snackbar } from './snackbar';
|
||||
18
src/components/snackbar/snackbar.module.css
Normal file
18
src/components/snackbar/snackbar.module.css
Normal file
@@ -0,0 +1,18 @@
|
||||
.wrapper {
|
||||
position: fixed;
|
||||
z-index: 100;
|
||||
bottom: 24px;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
|
||||
& .snackbar {
|
||||
width: max-content;
|
||||
max-width: 90%;
|
||||
padding: 12px 16px;
|
||||
border: 1px solid var(--color-neutral-300);
|
||||
border-radius: 4px;
|
||||
margin: 0 auto;
|
||||
background-color: var(--color-neutral-200);
|
||||
font-size: var(--font-sm);
|
||||
}
|
||||
}
|
||||
27
src/components/snackbar/snackbar.tsx
Normal file
27
src/components/snackbar/snackbar.tsx
Normal file
@@ -0,0 +1,27 @@
|
||||
import { motion } from 'framer-motion';
|
||||
|
||||
import { mix, fade, slideY } from '@/lib/motion';
|
||||
|
||||
import styles from './snackbar.module.css';
|
||||
|
||||
interface SnackbarProps {
|
||||
message: string;
|
||||
}
|
||||
|
||||
export function Snackbar({ message }: SnackbarProps) {
|
||||
const variants = mix(fade(), slideY(20, 0));
|
||||
|
||||
return (
|
||||
<div className={styles.wrapper}>
|
||||
<motion.div
|
||||
animate="show"
|
||||
className={styles.snackbar}
|
||||
exit="hidden"
|
||||
initial="hidden"
|
||||
variants={variants}
|
||||
>
|
||||
{message}
|
||||
</motion.div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user