Skip to content

Commit

Permalink
feat: add simple notepad
Browse files Browse the repository at this point in the history
  • Loading branch information
remvze committed Feb 24, 2024
1 parent 38c11f1 commit e923559
Show file tree
Hide file tree
Showing 15 changed files with 157 additions and 5 deletions.
3 changes: 2 additions & 1 deletion src/components/menu/item/item.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
align-items: center;
justify-content: flex-start;
width: 100%;
padding: 16px 12px;
height: 50px;
padding: 0 12px;
font-size: var(--font-sm);
font-weight: 500;
line-height: 1;
Expand Down
1 change: 1 addition & 0 deletions src/components/menu/items/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export { Shuffle as ShuffleItem } from './shuffle';
export { Share as ShareItem } from './share';
export { Donate as DonateItem } from './donate';
export { Notepad as NotepadItem } from './notepad';
11 changes: 11 additions & 0 deletions src/components/menu/items/notepad.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { MdNotes } from 'react-icons/md/index';

import { Item } from '../item';

interface NotepadProps {
open: () => void;
}

export function Notepad({ open }: NotepadProps) {
return <Item icon={<MdNotes />} label="Notepad" onClick={open} />;
}
7 changes: 6 additions & 1 deletion src/components/menu/menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ import {
FloatingFocusManager,
} from '@floating-ui/react';

import { ShuffleItem, ShareItem, DonateItem } from './items';
import { ShuffleItem, ShareItem, DonateItem, NotepadItem } from './items';
import { ShareLinkModal } from '@/components/modals/share-link';
import { Notepad } from '@/components/toolbox';

import { slideY, fade, mix } from '@/lib/motion';

Expand All @@ -25,6 +26,7 @@ export function Menu() {
const [isOpen, setIsOpen] = useState(false);

const [showShareLink, setShowShareLink] = useState(false);
const [showNotepad, setShowNotepad] = useState(false);

const variants = mix(slideY(-20), fade());

Expand Down Expand Up @@ -76,6 +78,7 @@ export function Menu() {
>
<ShareItem open={() => setShowShareLink(true)} />
<ShuffleItem />
<NotepadItem open={() => setShowNotepad(true)} />
<DonateItem />
</motion.div>
</div>
Expand All @@ -88,6 +91,8 @@ export function Menu() {
show={showShareLink}
onClose={() => setShowShareLink(false)}
/>

<Notepad show={showNotepad} onClose={() => setShowNotepad(false)} />
</>
);
}
7 changes: 7 additions & 0 deletions src/components/modal/modal.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@
background-color: var(--color-neutral-100);
border-radius: 8px;

&.wide {
width: 95%;
max-width: 600px;
padding: 12px;
padding-top: 40px;
}

& .close {
position: absolute;
top: 10px;
Expand Down
6 changes: 4 additions & 2 deletions src/components/modal/modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,18 @@ import { AnimatePresence, motion } from 'framer-motion';
import { IoClose } from 'react-icons/io5/index';

import { fade, mix, slideY } from '@/lib/motion';
import { cn } from '@/helpers/styles';

import styles from './modal.module.css';

interface ModalProps {
children: React.ReactNode;
onClose: () => void;
show: boolean;
wide?: boolean;
}

export function Modal({ children, onClose, show }: ModalProps) {
export function Modal({ children, onClose, show, wide }: ModalProps) {
const variants = {
modal: mix(fade(), slideY(20)),
overlay: fade(),
Expand All @@ -33,7 +35,7 @@ export function Modal({ children, onClose, show }: ModalProps) {
<div className={styles.modal}>
<motion.div
animate="show"
className={styles.content}
className={cn(styles.content, wide && styles.wide)}
exit="hidden"
initial="hidden"
variants={variants.modal}
Expand Down
3 changes: 2 additions & 1 deletion src/components/store-consumer/store-consumer.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useEffect } from 'react';

import { useSoundStore } from '@/store';
import { useSoundStore, useNoteStore } from '@/store';

interface StoreConsumerProps {
children: React.ReactNode;
Expand All @@ -9,6 +9,7 @@ interface StoreConsumerProps {
export function StoreConsumer({ children }: StoreConsumerProps) {
useEffect(() => {
useSoundStore.persist.rehydrate();
useNoteStore.persist.rehydrate();
}, []);

return <>{children}</>;
Expand Down
1 change: 1 addition & 0 deletions src/components/toolbox/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { Notepad } from './notepad';
1 change: 1 addition & 0 deletions src/components/toolbox/notepad/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { Notepad } from './notepad';
26 changes: 26 additions & 0 deletions src/components/toolbox/notepad/notepad.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
.header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 8px;

& .label {
font-size: var(--font-sm);
font-weight: 500;
color: var(--color-foreground-subtle);
}
}

.textarea {
width: 100%;
height: 350px;
padding: 12px;
line-height: 1.6;
color: var(--color-foreground-subtle);
resize: none;
background-color: var(--color-neutral-50);
border: 1px solid var(--color-neutral-200);
border-radius: 4px;
outline: none;
scroll-padding-bottom: 12px;
}
29 changes: 29 additions & 0 deletions src/components/toolbox/notepad/notepad.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { Modal } from '@/components/modal';

import styles from './notepad.module.css';
import { useNoteStore } from '@/store';

interface NotepadProps {
onClose: () => void;
show: boolean;
}

export function Notepad({ onClose, show }: NotepadProps) {
const note = useNoteStore(state => state.note);
const write = useNoteStore(state => state.write);

return (
<Modal show={show} wide onClose={onClose}>
<header className={styles.header}>
<h2 className={styles.label}>Your Note</h2>
</header>

<textarea
className={styles.textarea}
dir="auto"
value={note}
onChange={e => write(e.target.value)}
/>
</Modal>
);
}
1 change: 1 addition & 0 deletions src/store/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export { useSoundStore } from './sound';
export { useLoadingStore } from './loading';
export { useNoteStore } from './note';
28 changes: 28 additions & 0 deletions src/store/note/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { create } from 'zustand';
import { createJSONStorage, persist } from 'zustand/middleware';
import merge from 'deepmerge';

import { type NoteState, createState } from './note.state';
import { type NoteActions, createActions } from './note.actions';

export const useNoteStore = create<NoteState & NoteActions>()(
persist(
(...a) => ({
...createState(...a),
...createActions(...a),
}),
{
merge: (persisted, current) =>
merge(
current,
// @ts-ignore
persisted,
),
name: 'moodist-note',
partialize: state => ({ note: state.note }),
skipHydration: true,
storage: createJSONStorage(() => localStorage),
version: 0,
},
),
);
20 changes: 20 additions & 0 deletions src/store/note/note.actions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import type { StateCreator } from 'zustand';

import type { NoteState } from './note.state';

export interface NoteActions {
write: (note: string) => void;
}

export const createActions: StateCreator<
NoteActions & NoteState,
[],
[],
NoteActions
> = set => {
return {
write(note) {
set({ note });
},
};
};
18 changes: 18 additions & 0 deletions src/store/note/note.state.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import type { StateCreator } from 'zustand';

import type { NoteActions } from './note.actions';

export interface NoteState {
history: string | null;
note: string;
}

export const createState: StateCreator<
NoteState & NoteActions,
[],
[],
NoteState
> = () => ({
history: null,
note: '',
});

0 comments on commit e923559

Please sign in to comment.