UI improvements!

This commit is contained in:
Geert Rademakes 2025-04-24 16:08:06 +02:00
parent 3e8141aeba
commit 5c62f9d147
5 changed files with 108 additions and 56 deletions

View File

@ -1,8 +1,7 @@
#root { #root {
max-width: 1280px; max-width: 1280px;
margin: 0 auto; margin: 0;
padding: 2rem; padding: 1rem;
text-align: center;
} }
.logo { .logo {
@ -34,7 +33,7 @@
} }
.card { .card {
padding: 2em; padding: 1em;
} }
.read-the-docs { .read-the-docs {

View File

@ -56,16 +56,24 @@ export default function RekordboxReader() {
} }
return ( return (
<Box p={5}> <Box>
<Heading mb={4}>Rekordbox Reader</Heading> <Flex direction="column" gap={2} mb={4}>
<Heading size="md">Rekordbox Reader</Heading>
<Input <Input
type="file" type="file"
accept=".xml" accept=".xml"
onChange={handleFileUpload} onChange={handleFileUpload}
mb={4} size="sm"
width="auto"
/> />
<Flex gap={4}> {songs.length > 0 && (
<Box w="250px"> <Button onClick={handleExport} size="sm" colorScheme="blue" width="auto">
Export XML
</Button>
)}
</Flex>
<Flex gap={4} alignItems="start">
<Box w="200px">
<PlaylistManager <PlaylistManager
playlists={playlists} playlists={playlists}
selectedItem={selectedItem} selectedItem={selectedItem}
@ -81,11 +89,6 @@ export default function RekordboxReader() {
/> />
</Box> </Box>
</Flex> </Flex>
{songs.length > 0 && (
<Button onClick={handleExport} mt={4} colorScheme="blue">
Export XML
</Button>
)}
</Box> </Box>
); );
} }

View File

@ -1,9 +1,9 @@
import { import {
Button, Button,
Input, Input,
Flex, Stack,
Text,
useDisclosure, useDisclosure,
CloseButton,
} from "@chakra-ui/react"; } from "@chakra-ui/react";
import { import {
Modal, Modal,
@ -12,7 +12,6 @@ import {
ModalHeader, ModalHeader,
ModalFooter, ModalFooter,
ModalBody, ModalBody,
ModalCloseButton,
} from "@chakra-ui/modal"; } from "@chakra-ui/modal";
import { useState } from "react"; import { useState } from "react";
import { Playlist } from "../types/interfaces"; import { Playlist } from "../types/interfaces";
@ -30,23 +29,24 @@ export const PlaylistManager: React.FC<PlaylistManagerProps> = ({
onPlaylistCreate, onPlaylistCreate,
onPlaylistSelect, onPlaylistSelect,
}) => { }) => {
const disclosure = useDisclosure(); const { open, onOpen, onClose } = useDisclosure();
const [newPlaylistName, setNewPlaylistName] = useState(""); const [newPlaylistName, setNewPlaylistName] = useState("");
const handleCreatePlaylist = () => { const handleCreatePlaylist = () => {
if (newPlaylistName.trim()) { if (newPlaylistName.trim()) {
onPlaylistCreate(newPlaylistName); onPlaylistCreate(newPlaylistName);
setNewPlaylistName(""); setNewPlaylistName("");
disclosure.onClose(); onClose();
} }
}; };
return ( return (
<> <>
<Flex direction="column" gap={2}> <Stack gap={2}>
<Button <Button
onClick={() => onPlaylistSelect("All Songs")} onClick={() => onPlaylistSelect("All Songs")}
colorScheme={selectedItem === "All Songs" ? "blue" : "gray"} colorScheme={selectedItem === "All Songs" ? "blue" : "gray"}
size="sm"
> >
All Songs All Songs
</Button> </Button>
@ -55,32 +55,72 @@ export const PlaylistManager: React.FC<PlaylistManagerProps> = ({
key={playlist.name} key={playlist.name}
onClick={() => onPlaylistSelect(playlist.name)} onClick={() => onPlaylistSelect(playlist.name)}
colorScheme={selectedItem === playlist.name ? "blue" : "gray"} colorScheme={selectedItem === playlist.name ? "blue" : "gray"}
size="sm"
> >
{playlist.name} {playlist.name}
</Button> </Button>
))} ))}
<Button onClick={disclosure.onOpen} colorScheme="green"> <Button onClick={onOpen} colorScheme="green" size="sm">
Create New Playlist Create New Playlist
</Button> </Button>
</Flex> </Stack>
<Modal isOpen={disclosure.open} onClose={disclosure.onClose}> <Modal
<ModalOverlay /> isOpen={open}
<ModalContent> onClose={onClose}
<ModalHeader>Create New Playlist</ModalHeader> isCentered
<ModalCloseButton /> motionPreset="slideInBottom"
<ModalBody> >
<ModalOverlay
style={{
backgroundColor: 'rgba(0, 0, 0, 0.4)',
backdropFilter: 'blur(2px)'
}}
/>
<ModalContent
padding={"1rem"}
bg="gray.20"
bgColor={"rgba(0, 0, 0, 1)"}
maxW="500px"
w="90%"
borderRadius={25}
boxShadow={100}
margin="0 auto"
marginTop="10%"
>
<ModalHeader color="gray.800" fontSize="lg" fontWeight="bold" pt={6} px={6}>
Create New Playlist
</ModalHeader>
<CloseButton
position="absolute"
right={'1rem'}
top={'1rem'}
onClick={onClose}
color="gray.600"
/>
<ModalBody px={6} py={8} paddingTop="2rem">
<Input <Input
value={newPlaylistName} value={newPlaylistName}
onChange={(e) => setNewPlaylistName(e.target.value)} onChange={(e) => setNewPlaylistName(e.target.value)}
placeholder="Playlist name" placeholder="Enter playlist name"
autoFocus
size="lg"
color="gray.800"
_placeholder={{ color: 'gray.400' }}
onKeyDown={(e) => {
if (e.key === 'Enter') {
handleCreatePlaylist();
}
}}
/> />
</ModalBody> </ModalBody>
<ModalFooter> <ModalFooter px={6} py={4} borderTop="1px" borderColor="gray.100">
<Button colorScheme="blue" mr={3} onClick={handleCreatePlaylist}> <Button colorScheme="blue" mr={3} onClick={handleCreatePlaylist} size="md" px={8}>
Create Create
</Button> </Button>
<Button onClick={disclosure.onClose}>Cancel</Button> <Button onClick={onClose} size="md" variant="ghost" color="gray.600">
Cancel
</Button>
</ModalFooter> </ModalFooter>
</ModalContent> </ModalContent>
</Modal> </Modal>

View File

@ -1,5 +1,6 @@
import { Box, Flex, Text } from "@chakra-ui/react"; import { Box, Flex, Text } from "@chakra-ui/react";
import { Song } from "../types/interfaces"; import { Song } from "../types/interfaces";
import { ChangeEvent } from "react";
interface SongListProps { interface SongListProps {
songs: Song[]; songs: Song[];
@ -9,14 +10,23 @@ interface SongListProps {
export const SongList: React.FC<SongListProps> = ({ songs, onAddToPlaylist, playlists }) => { export const SongList: React.FC<SongListProps> = ({ songs, onAddToPlaylist, playlists }) => {
return ( return (
<Flex direction="column" gap={4}> <Flex direction="column" gap={2}>
{songs.map((song) => ( {songs.map((song) => (
<Box key={song.id} borderWidth="1px" borderRadius="lg" p={4} shadow="md"> <Box key={song.id} borderWidth="1px" borderRadius="md" p={2} shadow="sm">
<Text fontWeight="bold">{song.title}</Text> <Flex justify="space-between" align="center">
<Text color="gray.500">{song.artist}</Text> <Box>
<Text fontWeight="bold" fontSize="sm">{song.title}</Text>
<Text color="gray.500" fontSize="xs">{song.artist}</Text>
</Box>
<select <select
onChange={(e) => onAddToPlaylist(song.id, e.target.value)} onChange={(e: ChangeEvent<HTMLSelectElement>) => onAddToPlaylist(song.id, e.target.value)}
value="" value=""
style={{
padding: '0.25rem',
fontSize: '0.875rem',
borderRadius: '0.375rem',
border: '1px solid #E2E8F0'
}}
> >
<option value="" disabled>Add to playlist</option> <option value="" disabled>Add to playlist</option>
{playlists.map((playlist) => ( {playlists.map((playlist) => (
@ -25,6 +35,7 @@ export const SongList: React.FC<SongListProps> = ({ songs, onAddToPlaylist, play
</option> </option>
))} ))}
</select> </select>
</Flex>
</Box> </Box>
))} ))}
</Flex> </Flex>

View File

@ -24,21 +24,20 @@ a:hover {
body { body {
margin: 0; margin: 0;
display: flex;
place-items: center;
min-width: 320px; min-width: 320px;
min-height: 100vh; min-height: 100vh;
} }
h1 { h1 {
font-size: 3.2em; font-size: 2em;
line-height: 1.1; line-height: 1.1;
margin: 0;
} }
button { button {
border-radius: 8px; border-radius: 8px;
border: 1px solid transparent; border: 1px solid transparent;
padding: 0.6em 1.2em; padding: 0.4em 0.8em;
font-size: 1em; font-size: 1em;
font-weight: 500; font-weight: 500;
font-family: inherit; font-family: inherit;