feat: add music examples
This commit is contained in:
parent
a8ebf5ea73
commit
6b747b14a4
|
|
@ -38,7 +38,7 @@
|
|||
"postcss": "^8.4.24",
|
||||
"radix-vue": "^0.1.30",
|
||||
"tailwind-merge": "^1.14.0",
|
||||
"tailwindcss": "^3.3.2",
|
||||
"tailwindcss": "^3.3.3",
|
||||
"typescript": "^5.0.2",
|
||||
"unplugin-icons": "^0.16.6",
|
||||
"vite": "^4.3.9",
|
||||
|
|
|
|||
5
apps/www/src/content/examples/music.md
Normal file
5
apps/www/src/content/examples/music.md
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<script setup>
|
||||
import MusicExample from "@/examples/music/Example.vue"
|
||||
</script>
|
||||
|
||||
<MusicExample />
|
||||
147
apps/www/src/examples/music/Example.vue
Normal file
147
apps/www/src/examples/music/Example.vue
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
<script setup lang="ts">
|
||||
import AlbumArtwork from './components/AlbumArtwork.vue'
|
||||
import Menu from './components/Menu.vue'
|
||||
import PodcastEmptyPlaceholder from './components/PodcastEmptyPlaceholder.vue'
|
||||
import Sidebar from './components/Sidebar.vue'
|
||||
|
||||
import { listenNowAlbums, madeForYouAlbums } from './data/albums'
|
||||
import { playlists } from './data/playlists'
|
||||
import {
|
||||
Tabs,
|
||||
TabsContent,
|
||||
TabsList,
|
||||
TabsTrigger,
|
||||
} from '@/lib/registry/default/ui/tabs'
|
||||
import { Separator } from '@/lib/registry/default/ui/separator'
|
||||
import { Button } from '@/lib/registry/default/ui/button'
|
||||
import { ScrollArea, ScrollBar } from '@/lib/registry/default/ui/scroll-area'
|
||||
import PlusCircledIcon from '~icons/radix-icons/plus-circled'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- <div class="md:hidden">
|
||||
<Image
|
||||
src="/examples/music-light.png"
|
||||
width={1280}
|
||||
height={1114}
|
||||
alt="Music"
|
||||
class="block dark:hidden"
|
||||
/>
|
||||
<Image
|
||||
src="/examples/music-dark.png"
|
||||
width={1280}
|
||||
height={1114}
|
||||
alt="Music"
|
||||
class="hidden dark:block"
|
||||
/>
|
||||
</div> -->
|
||||
<div class="hidden md:block">
|
||||
<Menu />
|
||||
<div class="border-t">
|
||||
<div class="bg-background">
|
||||
<div class="grid lg:grid-cols-5">
|
||||
<Sidebar :playlists="playlists" class="hidden lg:block" />
|
||||
<div class="col-span-3 lg:col-span-4 lg:border-l">
|
||||
<div class="h-full px-4 py-6 lg:px-8">
|
||||
<Tabs default-value="music" class="h-full space-y-6">
|
||||
<div class="space-between flex items-center">
|
||||
<TabsList>
|
||||
<TabsTrigger value="music" class="relative">
|
||||
Music
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="podcasts">
|
||||
Podcasts
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="live" disabled>
|
||||
Live
|
||||
</TabsTrigger>
|
||||
</TabsList>
|
||||
<div class="ml-auto mr-4">
|
||||
<Button>
|
||||
<PlusCircledIcon class="mr-2 h-4 w-4" />
|
||||
Add music
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<TabsContent
|
||||
value="music"
|
||||
class="border-none p-0 outline-none"
|
||||
>
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="space-y-1">
|
||||
<h2 class="text-2xl font-semibold tracking-tight">
|
||||
Listen Now
|
||||
</h2>
|
||||
<p class="text-sm text-muted-foreground">
|
||||
Top picks for you. Updated daily.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<Separator class="my-4" />
|
||||
<div class="relative">
|
||||
<ScrollArea>
|
||||
<div class="flex space-x-4 pb-4">
|
||||
<AlbumArtwork
|
||||
v-for="album in listenNowAlbums"
|
||||
:key="album.name"
|
||||
:album="album"
|
||||
class="w-[250px]"
|
||||
aspect-ratio="portrait"
|
||||
:width="250"
|
||||
:height="330"
|
||||
/>
|
||||
</div>
|
||||
<ScrollBar orientation="horizontal" />
|
||||
</ScrollArea>
|
||||
</div>
|
||||
<div class="mt-6 space-y-1">
|
||||
<h2 class="text-2xl font-semibold tracking-tight">
|
||||
Made for You
|
||||
</h2>
|
||||
<p class="text-sm text-muted-foreground">
|
||||
Your personal playlists. Updated daily.
|
||||
</p>
|
||||
</div>
|
||||
<Separator class="my-4" />
|
||||
<div class="relative">
|
||||
<ScrollArea>
|
||||
<div class="flex space-x-4 pb-4">
|
||||
<AlbumArtwork
|
||||
v-for="album in madeForYouAlbums"
|
||||
:key="album.name"
|
||||
:album="album"
|
||||
class="w-[150px]"
|
||||
aspect-ratio="square"
|
||||
:width="150"
|
||||
:height="150"
|
||||
/>
|
||||
</div>
|
||||
<ScrollBar orientation="horizontal" />
|
||||
</ScrollArea>
|
||||
</div>
|
||||
</TabsContent>
|
||||
<TabsContent
|
||||
value="podcasts"
|
||||
class="h-full flex-col border-none p-0 data-[state=active]:flex"
|
||||
>
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="space-y-1">
|
||||
<h2 class="text-2xl font-semibold tracking-tight">
|
||||
New Episodes
|
||||
</h2>
|
||||
<p class="text-sm text-muted-foreground">
|
||||
Your favorite podcasts. Updated daily.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<Separator class="my-4" />
|
||||
<PodcastEmptyPlaceholder />
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
91
apps/www/src/examples/music/components/AlbumArtwork.vue
Normal file
91
apps/www/src/examples/music/components/AlbumArtwork.vue
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
<script setup lang="ts">
|
||||
import type { Album } from '../data/albums'
|
||||
import { playlists } from '../data/playlists'
|
||||
import PlusCircledIcon from '~icons/radix-icons/plus-circled'
|
||||
import { cn } from '@/lib/utils'
|
||||
import {
|
||||
ContextMenu,
|
||||
ContextMenuContent,
|
||||
ContextMenuItem,
|
||||
ContextMenuSeparator,
|
||||
ContextMenuSub,
|
||||
ContextMenuSubContent,
|
||||
ContextMenuSubTrigger,
|
||||
ContextMenuTrigger,
|
||||
} from '@/lib/registry/default/ui/context-menu'
|
||||
|
||||
interface AlbumArtworkProps {
|
||||
album: Album
|
||||
aspectRatio?: 'portrait' | 'square'
|
||||
width?: number
|
||||
height?: number
|
||||
}
|
||||
withDefaults(defineProps<AlbumArtworkProps>(), {
|
||||
aspectRatio: 'portrait',
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div :class="cn('space-y-3', $attrs.class ?? '')">
|
||||
<ContextMenu>
|
||||
<ContextMenuTrigger>
|
||||
<div class="overflow-hidden rounded-md">
|
||||
<img
|
||||
:src="album.cover"
|
||||
:alt="album.name"
|
||||
:width="width"
|
||||
:height="height"
|
||||
|
||||
:class="cn(
|
||||
'h-auto w-auto object-cover transition-all hover:scale-105',
|
||||
aspectRatio === 'portrait' ? 'aspect-[3/4]' : 'aspect-square',
|
||||
)"
|
||||
>
|
||||
</div>
|
||||
</ContextMenuTrigger>
|
||||
<ContextMenuContent class="w-40">
|
||||
<ContextMenuItem>Add to Library</ContextMenuItem>
|
||||
<ContextMenuSub>
|
||||
<ContextMenuSubTrigger>Add to Playlist</ContextMenuSubTrigger>
|
||||
<ContextMenuSubContent class="w-48">
|
||||
<ContextMenuItem>
|
||||
<PlusCircledIcon class="mr-2 h-4 w-4" />
|
||||
New Playlist
|
||||
</ContextMenuItem>
|
||||
<ContextMenuSeparator />
|
||||
<ContextMenuItem v-for="playlist in playlists" :key="playlist">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
class="mr-2 h-4 w-4"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path d="M21 15V6M18.5 18a2.5 2.5 0 1 0 0-5 2.5 2.5 0 0 0 0 5ZM12 12H3M16 6H3M12 18H3" />
|
||||
</svg>
|
||||
{{ playlist }}
|
||||
</ContextMenuItem>
|
||||
</ContextMenuSubContent>
|
||||
</ContextMenuSub>
|
||||
<ContextMenuSeparator />
|
||||
<ContextMenuItem>Play Next</ContextMenuItem>
|
||||
<ContextMenuItem>Play Later</ContextMenuItem>
|
||||
<ContextMenuItem>Create Station</ContextMenuItem>
|
||||
<ContextMenuSeparator />
|
||||
<ContextMenuItem>Like</ContextMenuItem>
|
||||
<ContextMenuItem>Share</ContextMenuItem>
|
||||
</ContextMenuContent>
|
||||
</ContextMenu>
|
||||
<div class="space-y-1 text-sm">
|
||||
<h3 class="font-medium leading-none">
|
||||
{{ album.name }}
|
||||
</h3>
|
||||
<p class="text-xs text-muted-foreground">
|
||||
{{ album.artist }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
230
apps/www/src/examples/music/components/Menu.vue
Normal file
230
apps/www/src/examples/music/components/Menu.vue
Normal file
|
|
@ -0,0 +1,230 @@
|
|||
<script setup lang="ts">
|
||||
import {
|
||||
Menubar,
|
||||
MenubarCheckboxItem,
|
||||
MenubarContent,
|
||||
MenubarItem,
|
||||
MenubarLabel,
|
||||
MenubarMenu,
|
||||
MenubarRadioGroup,
|
||||
MenubarRadioItem,
|
||||
MenubarSeparator,
|
||||
MenubarShortcut,
|
||||
MenubarSub,
|
||||
MenubarSubContent,
|
||||
MenubarSubTrigger,
|
||||
MenubarTrigger,
|
||||
} from '@/lib/registry/default/ui/menubar'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Menubar class="rounded-none border-b border-none px-2 lg:px-4">
|
||||
<MenubarMenu>
|
||||
<MenubarTrigger class="font-bold">
|
||||
Music
|
||||
</MenubarTrigger>
|
||||
<MenubarContent>
|
||||
<MenubarItem>About Music</MenubarItem>
|
||||
<MenubarSeparator />
|
||||
<MenubarItem>
|
||||
Preferences... <MenubarShortcut>⌘,</MenubarShortcut>
|
||||
</MenubarItem>
|
||||
<MenubarSeparator />
|
||||
<MenubarItem>
|
||||
Hide Music... <MenubarShortcut>⌘H</MenubarShortcut>
|
||||
</MenubarItem>
|
||||
<MenubarItem>
|
||||
Hide Others... <MenubarShortcut>⇧⌘H</MenubarShortcut>
|
||||
</MenubarItem>
|
||||
<MenubarShortcut />
|
||||
<MenubarItem>
|
||||
Quit Music <MenubarShortcut>⌘Q</MenubarShortcut>
|
||||
</MenubarItem>
|
||||
</MenubarContent>
|
||||
</MenubarMenu>
|
||||
<MenubarMenu>
|
||||
<MenubarTrigger class="relative">
|
||||
File
|
||||
</MenubarTrigger>
|
||||
<MenubarContent>
|
||||
<MenubarSub>
|
||||
<MenubarSubTrigger>New</MenubarSubTrigger>
|
||||
<MenubarSubContent class="w-[230px]">
|
||||
<MenubarItem>
|
||||
Playlist <MenubarShortcut>⌘N</MenubarShortcut>
|
||||
</MenubarItem>
|
||||
<MenubarItem disabled>
|
||||
Playlist from Selection <MenubarShortcut>⇧⌘N</MenubarShortcut>
|
||||
</MenubarItem>
|
||||
<MenubarItem>
|
||||
Smart Playlist... <MenubarShortcut>⌥⌘N</MenubarShortcut>
|
||||
</MenubarItem>
|
||||
<MenubarItem>Playlist Folder</MenubarItem>
|
||||
<MenubarItem disabled>
|
||||
Genius Playlist
|
||||
</MenubarItem>
|
||||
</MenubarSubContent>
|
||||
</MenubarSub>
|
||||
<MenubarItem>
|
||||
Open Stream URL... <MenubarShortcut>⌘U</MenubarShortcut>
|
||||
</MenubarItem>
|
||||
<MenubarItem>
|
||||
Close Window <MenubarShortcut>⌘W</MenubarShortcut>
|
||||
</MenubarItem>
|
||||
<MenubarSeparator />
|
||||
<MenubarSub>
|
||||
<MenubarSubTrigger>Library</MenubarSubTrigger>
|
||||
<MenubarSubContent>
|
||||
<MenubarItem>Update Cloud Library</MenubarItem>
|
||||
<MenubarItem>Update Genius</MenubarItem>
|
||||
<MenubarSeparator />
|
||||
<MenubarItem>Organize Library...</MenubarItem>
|
||||
<MenubarItem>Export Library...</MenubarItem>
|
||||
<MenubarSeparator />
|
||||
<MenubarItem>Import Playlist...</MenubarItem>
|
||||
<MenubarItem disabled>
|
||||
Export Playlist...
|
||||
</MenubarItem>
|
||||
<MenubarItem>Show Duplicate Items</MenubarItem>
|
||||
<MenubarSeparator />
|
||||
<MenubarItem>Get Album Artwork</MenubarItem>
|
||||
<MenubarItem disabled>
|
||||
Get Track Names
|
||||
</MenubarItem>
|
||||
</MenubarSubContent>
|
||||
</MenubarSub>
|
||||
<MenubarItem>
|
||||
Import... <MenubarShortcut>⌘O</MenubarShortcut>
|
||||
</MenubarItem>
|
||||
<MenubarItem disabled>
|
||||
Burn Playlist to Disc...
|
||||
</MenubarItem>
|
||||
<MenubarSeparator />
|
||||
<MenubarItem>
|
||||
Show in Finder <MenubarShortcut>⇧⌘R</MenubarShortcut>
|
||||
</MenubarItem>
|
||||
<MenubarItem>Convert</MenubarItem>
|
||||
<MenubarSeparator />
|
||||
<MenubarItem>Page Setup...</MenubarItem>
|
||||
<MenubarItem disabled>
|
||||
Print... <MenubarShortcut>⌘P</MenubarShortcut>
|
||||
</MenubarItem>
|
||||
</MenubarContent>
|
||||
</MenubarMenu>
|
||||
<MenubarMenu>
|
||||
<MenubarTrigger>Edit</MenubarTrigger>
|
||||
<MenubarContent>
|
||||
<MenubarItem disabled>
|
||||
Undo <MenubarShortcut>⌘Z</MenubarShortcut>
|
||||
</MenubarItem>
|
||||
<MenubarItem disabled>
|
||||
Redo <MenubarShortcut>⇧⌘Z</MenubarShortcut>
|
||||
</MenubarItem>
|
||||
<MenubarSeparator />
|
||||
<MenubarItem disabled>
|
||||
Cut <MenubarShortcut>⌘X</MenubarShortcut>
|
||||
</MenubarItem>
|
||||
<MenubarItem disabled>
|
||||
Copy <MenubarShortcut>⌘C</MenubarShortcut>
|
||||
</MenubarItem>
|
||||
<MenubarItem disabled>
|
||||
Paste <MenubarShortcut>⌘V</MenubarShortcut>
|
||||
</MenubarItem>
|
||||
<MenubarSeparator />
|
||||
<MenubarItem>
|
||||
Select All <MenubarShortcut>⌘A</MenubarShortcut>
|
||||
</MenubarItem>
|
||||
<MenubarItem disabled>
|
||||
Deselect All <MenubarShortcut>⇧⌘A</MenubarShortcut>
|
||||
</MenubarItem>
|
||||
<MenubarSeparator />
|
||||
<MenubarItem>
|
||||
Smart Dictation...
|
||||
<MenubarShortcut>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
class="h-4 w-4"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path d="m12 8-9.04 9.06a2.82 2.82 0 1 0 3.98 3.98L16 12" />
|
||||
<circle cx="17" cy="7" r="5" />
|
||||
</svg>
|
||||
</MenubarShortcut>
|
||||
</MenubarItem>
|
||||
<MenubarItem>
|
||||
Emoji & Symbols
|
||||
<MenubarShortcut>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
class="h-4 w-4"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<circle cx="12" cy="12" r="10" />
|
||||
<path d="M2 12h20M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z" />
|
||||
</svg>
|
||||
</MenubarShortcut>
|
||||
</MenubarItem>
|
||||
</MenubarContent>
|
||||
</MenubarMenu>
|
||||
<MenubarMenu>
|
||||
<MenubarTrigger>View</MenubarTrigger>
|
||||
<MenubarContent>
|
||||
<MenubarCheckboxItem>Show Playing Next</MenubarCheckboxItem>
|
||||
<MenubarCheckboxItem checked>
|
||||
Show Lyrics
|
||||
</MenubarCheckboxItem>
|
||||
<MenubarSeparator />
|
||||
<MenubarItem inset disabled>
|
||||
Show Status Bar
|
||||
</MenubarItem>
|
||||
<MenubarSeparator />
|
||||
<MenubarItem inset>
|
||||
Hide Sidebar
|
||||
</MenubarItem>
|
||||
<MenubarItem disabled inset>
|
||||
Enter Full Screen
|
||||
</MenubarItem>
|
||||
</MenubarContent>
|
||||
</MenubarMenu>
|
||||
<MenubarMenu>
|
||||
<MenubarTrigger class="hidden md:block">
|
||||
Account
|
||||
</MenubarTrigger>
|
||||
<MenubarContent force-mount>
|
||||
<MenubarLabel inset>
|
||||
Switch Account
|
||||
</MenubarLabel>
|
||||
<MenubarSeparator />
|
||||
<MenubarRadioGroup value="benoit">
|
||||
<MenubarRadioItem value="andy">
|
||||
Andy
|
||||
</MenubarRadioItem>
|
||||
<MenubarRadioItem value="benoit">
|
||||
Benoit
|
||||
</MenubarRadioItem>
|
||||
<MenubarRadioItem value="Luis">
|
||||
Luis
|
||||
</MenubarRadioItem>
|
||||
</MenubarRadioGroup>
|
||||
<MenubarSeparator />
|
||||
<MenubarItem inset>
|
||||
Manage Famliy...
|
||||
</MenubarItem>
|
||||
<MenubarSeparator />
|
||||
<MenubarItem inset>
|
||||
Add Account...
|
||||
</MenubarItem>
|
||||
</MenubarContent>
|
||||
</MenubarMenu>
|
||||
</Menubar>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
<script setup lang="ts">
|
||||
import { Button } from '@/lib/registry/default/ui/button'
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from '@/lib/registry/default/ui/dialog'
|
||||
import { Input } from '@/lib/registry/default/ui/input'
|
||||
import { Label } from '@/lib/registry/default/ui/label'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex h-[450px] shrink-0 items-center justify-center rounded-md border border-dashed">
|
||||
<div class="mx-auto flex max-w-[420px] flex-col items-center justify-center text-center">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
class="h-10 w-10 text-muted-foreground"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<circle cx="12" cy="11" r="1" />
|
||||
<path d="M11 17a1 1 0 0 1 2 0c0 .5-.34 3-.5 4.5a.5.5 0 0 1-1 0c-.16-1.5-.5-4-.5-4.5ZM8 14a5 5 0 1 1 8 0" />
|
||||
<path d="M17 18.5a9 9 0 1 0-10 0" />
|
||||
</svg>
|
||||
|
||||
<h3 class="mt-4 text-lg font-semibold">
|
||||
No episodes added
|
||||
</h3>
|
||||
<p class="mb-4 mt-2 text-sm text-muted-foreground">
|
||||
You have not added any podcasts. Add one below.
|
||||
</p>
|
||||
<Dialog>
|
||||
<DialogTrigger>
|
||||
<Button size="sm" class="relative">
|
||||
Add Podcast
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent>
|
||||
<DialogHeader>
|
||||
<DialogTitle>Add Podcast</DialogTitle>
|
||||
<DialogDescription>
|
||||
Copy and paste the podcast feed URL to import.
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<div class="grid gap-4 py-4">
|
||||
<div class="grid gap-2">
|
||||
<Label for="url">Podcast URL</Label>
|
||||
<Input id="url" placeholder="https://example.com/feed.xml" />
|
||||
</div>
|
||||
</div>
|
||||
<DialogFooter>
|
||||
<Button>Import Podcast</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
204
apps/www/src/examples/music/components/Sidebar.vue
Normal file
204
apps/www/src/examples/music/components/Sidebar.vue
Normal file
|
|
@ -0,0 +1,204 @@
|
|||
<script setup lang="ts">
|
||||
import type { Playlist } from '../data/playlists'
|
||||
import { cn } from '@/lib/utils'
|
||||
import { Button } from '@/lib/registry/default/ui/button'
|
||||
import { ScrollArea } from '@/lib/registry/default/ui/scroll-area'
|
||||
|
||||
interface SidebarProps {
|
||||
playlists: Playlist[]
|
||||
}
|
||||
|
||||
defineProps<SidebarProps>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div :class="cn('pb-12', $attrs.class ?? '')">
|
||||
<div class="space-y-4 py-4">
|
||||
<div class="px-3 py-2">
|
||||
<h2 class="mb-2 px-4 text-lg font-semibold tracking-tight">
|
||||
Discover
|
||||
</h2>
|
||||
<div class="space-y-1">
|
||||
<Button variant="secondary" class="w-full justify-start">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
class="mr-2 h-4 w-4"
|
||||
>
|
||||
<circle cx="12" cy="12" r="10" />
|
||||
<polygon points="10 8 16 12 10 16 10 8" />
|
||||
</svg>
|
||||
Listen Now
|
||||
</Button>
|
||||
<Button variant="ghost" class="w-full justify-start">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
class="mr-2 h-4 w-4"
|
||||
>
|
||||
<rect width="7" height="7" x="3" y="3" rx="1" />
|
||||
<rect width="7" height="7" x="14" y="3" rx="1" />
|
||||
<rect width="7" height="7" x="14" y="14" rx="1" />
|
||||
<rect width="7" height="7" x="3" y="14" rx="1" />
|
||||
</svg>
|
||||
Browse
|
||||
</Button>
|
||||
<Button variant="ghost" class="w-full justify-start">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
class="mr-2 h-4 w-4"
|
||||
>
|
||||
<path d="M4.9 19.1C1 15.2 1 8.8 4.9 4.9" />
|
||||
<path d="M7.8 16.2c-2.3-2.3-2.3-6.1 0-8.5" />
|
||||
<circle cx="12" cy="12" r="2" />
|
||||
<path d="M16.2 7.8c2.3 2.3 2.3 6.1 0 8.5" />
|
||||
<path d="M19.1 4.9C23 8.8 23 15.1 19.1 19" />
|
||||
</svg>
|
||||
Radio
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="px-3 py-2">
|
||||
<h2 class="mb-2 px-4 text-lg font-semibold tracking-tight">
|
||||
Library
|
||||
</h2>
|
||||
<div class="space-y-1">
|
||||
<Button variant="ghost" class="w-full justify-start">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
class="mr-2 h-4 w-4"
|
||||
>
|
||||
<path d="M21 15V6" />
|
||||
<path d="M18.5 18a2.5 2.5 0 1 0 0-5 2.5 2.5 0 0 0 0 5Z" />
|
||||
<path d="M12 12H3" />
|
||||
<path d="M16 6H3" />
|
||||
<path d="M12 18H3" />
|
||||
</svg>
|
||||
Playlists
|
||||
</Button>
|
||||
<Button variant="ghost" class="w-full justify-start">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
class="mr-2 h-4 w-4"
|
||||
>
|
||||
<circle cx="8" cy="18" r="4" />
|
||||
<path d="M12 18V2l7 4" />
|
||||
</svg>
|
||||
Songs
|
||||
</Button>
|
||||
<Button variant="ghost" class="w-full justify-start">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
class="mr-2 h-4 w-4"
|
||||
>
|
||||
<path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2" />
|
||||
<circle cx="12" cy="7" r="4" />
|
||||
</svg>
|
||||
Made for You
|
||||
</Button>
|
||||
<Button variant="ghost" class="w-full justify-start">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
class="mr-2 h-4 w-4"
|
||||
>
|
||||
<path d="m12 8-9.04 9.06a2.82 2.82 0 1 0 3.98 3.98L16 12" />
|
||||
<circle cx="17" cy="7" r="5" />
|
||||
</svg>
|
||||
Artists
|
||||
</Button>
|
||||
<Button variant="ghost" class="w-full justify-start">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
class="mr-2 h-4 w-4"
|
||||
>
|
||||
<path d="m16 6 4 14" />
|
||||
<path d="M12 6v14" />
|
||||
<path d="M8 8v12" />
|
||||
<path d="M4 4v16" />
|
||||
</svg>
|
||||
Albums
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="py-2">
|
||||
<h2 class="relative px-7 text-lg font-semibold tracking-tight">
|
||||
Playlists
|
||||
</h2>
|
||||
<ScrollArea class="h-[300px] px-1">
|
||||
<div class="space-y-1 p-2">
|
||||
<Button
|
||||
v-for="(playlist, i) in playlists"
|
||||
:key="`${playlist}-${i}`"
|
||||
variant="ghost"
|
||||
class="w-full justify-start font-normal"
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
class="mr-2 h-4 w-4"
|
||||
>
|
||||
<path d="M21 15V6" />
|
||||
<path d="M18.5 18a2.5 2.5 0 1 0 0-5 2.5 2.5 0 0 0 0 5Z" />
|
||||
<path d="M12 12H3" />
|
||||
<path d="M16 6H3" />
|
||||
<path d="M12 18H3" />
|
||||
</svg>
|
||||
{{ playlist }}
|
||||
</Button>
|
||||
</div>
|
||||
</ScrollArea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
71
apps/www/src/examples/music/data/albums.ts
Normal file
71
apps/www/src/examples/music/data/albums.ts
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
export interface Album {
|
||||
name: string
|
||||
artist: string
|
||||
cover: string
|
||||
}
|
||||
|
||||
export const listenNowAlbums: Album[] = [
|
||||
{
|
||||
name: 'React Rendezvous',
|
||||
artist: 'Ethan Byte',
|
||||
cover:
|
||||
'https://images.unsplash.com/photo-1611348586804-61bf6c080437?w=300&dpr=2&q=80',
|
||||
},
|
||||
{
|
||||
name: 'Async Awakenings',
|
||||
artist: 'Nina Netcode',
|
||||
cover:
|
||||
'https://images.unsplash.com/photo-1468817814611-b7edf94b5d60?w=300&dpr=2&q=80',
|
||||
},
|
||||
{
|
||||
name: 'The Art of Reusability',
|
||||
artist: 'Lena Logic',
|
||||
cover:
|
||||
'https://images.unsplash.com/photo-1528143358888-6d3c7f67bd5d?w=300&dpr=2&q=80',
|
||||
},
|
||||
{
|
||||
name: 'Stateful Symphony',
|
||||
artist: 'Beth Binary',
|
||||
cover:
|
||||
'https://images.unsplash.com/photo-1490300472339-79e4adc6be4a?w=300&dpr=2&q=80',
|
||||
},
|
||||
]
|
||||
|
||||
export const madeForYouAlbums: Album[] = [
|
||||
{
|
||||
name: 'Thinking Components',
|
||||
artist: 'Lena Logic',
|
||||
cover:
|
||||
'https://images.unsplash.com/photo-1615247001958-f4bc92fa6a4a?w=300&dpr=2&q=80',
|
||||
},
|
||||
{
|
||||
name: 'Functional Fury',
|
||||
artist: 'Beth Binary',
|
||||
cover:
|
||||
'https://images.unsplash.com/photo-1513745405825-efaf9a49315f?w=300&dpr=2&q=80',
|
||||
},
|
||||
{
|
||||
name: 'React Rendezvous',
|
||||
artist: 'Ethan Byte',
|
||||
cover:
|
||||
'https://images.unsplash.com/photo-1614113489855-66422ad300a4?w=300&dpr=2&q=80',
|
||||
},
|
||||
{
|
||||
name: 'Stateful Symphony',
|
||||
artist: 'Beth Binary',
|
||||
cover:
|
||||
'https://images.unsplash.com/photo-1446185250204-f94591f7d702?w=300&dpr=2&q=80',
|
||||
},
|
||||
{
|
||||
name: 'Async Awakenings',
|
||||
artist: 'Nina Netcode',
|
||||
cover:
|
||||
'https://images.unsplash.com/photo-1468817814611-b7edf94b5d60?w=300&dpr=2&q=80',
|
||||
},
|
||||
{
|
||||
name: 'The Art of Reusability',
|
||||
artist: 'Lena Logic',
|
||||
cover:
|
||||
'https://images.unsplash.com/photo-1490300472339-79e4adc6be4a?w=300&dpr=2&q=80',
|
||||
},
|
||||
]
|
||||
16
apps/www/src/examples/music/data/playlists.ts
Normal file
16
apps/www/src/examples/music/data/playlists.ts
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
export type Playlist = (typeof playlists)[number]
|
||||
|
||||
export const playlists = [
|
||||
'Recently Added',
|
||||
'Recently Played',
|
||||
'Top Songs',
|
||||
'Top Albums',
|
||||
'Top Artists',
|
||||
'Logic Discography',
|
||||
'Bedtime Beats',
|
||||
'Feeling Happy',
|
||||
'I miss Y2K Pop',
|
||||
'Runtober',
|
||||
'Mellow Days',
|
||||
'Eminem Essentials',
|
||||
]
|
||||
|
|
@ -70,7 +70,7 @@ importers:
|
|||
version: 0.268.0(vue@3.3.4)
|
||||
tailwindcss-animate:
|
||||
specifier: ^1.0.6
|
||||
version: 1.0.6(tailwindcss@3.3.2)
|
||||
version: 1.0.6(tailwindcss@3.3.3)
|
||||
v-calendar:
|
||||
specifier: ^3.0.3
|
||||
version: 3.0.3(@popperjs/core@2.11.8)(vue@3.3.4)
|
||||
|
|
@ -118,8 +118,8 @@ importers:
|
|||
specifier: ^1.14.0
|
||||
version: 1.14.0
|
||||
tailwindcss:
|
||||
specifier: ^3.3.2
|
||||
version: 3.3.2(ts-node@10.9.1)
|
||||
specifier: ^3.3.3
|
||||
version: 3.3.3(ts-node@10.9.1)
|
||||
typescript:
|
||||
specifier: ^5.0.2
|
||||
version: 5.0.2
|
||||
|
|
@ -4598,16 +4598,6 @@ packages:
|
|||
engines: {node: '>=6.0.0'}
|
||||
dev: false
|
||||
|
||||
/fast-glob@3.3.0:
|
||||
resolution: {integrity: sha512-ChDuvbOypPuNjO8yIDf36x7BlZX1smcUMTTcyoIjycexOxd6DFsKsg21qVBzEmr3G7fUKIRy2/psii+CIUt7FA==}
|
||||
engines: {node: '>=8.6.0'}
|
||||
dependencies:
|
||||
'@nodelib/fs.stat': 2.0.5
|
||||
'@nodelib/fs.walk': 1.2.8
|
||||
glob-parent: 5.1.2
|
||||
merge2: 1.4.1
|
||||
micromatch: 4.0.5
|
||||
|
||||
/fast-glob@3.3.1:
|
||||
resolution: {integrity: sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==}
|
||||
engines: {node: '>=8.6.0'}
|
||||
|
|
@ -6261,27 +6251,27 @@ packages:
|
|||
enhanced-resolve: 4.5.0
|
||||
dev: false
|
||||
|
||||
/postcss-import@15.1.0(postcss@8.4.24):
|
||||
/postcss-import@15.1.0(postcss@8.4.28):
|
||||
resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==}
|
||||
engines: {node: '>=14.0.0'}
|
||||
peerDependencies:
|
||||
postcss: ^8.0.0
|
||||
dependencies:
|
||||
postcss: 8.4.24
|
||||
postcss: 8.4.28
|
||||
postcss-value-parser: 4.2.0
|
||||
read-cache: 1.0.0
|
||||
resolve: 1.22.4
|
||||
|
||||
/postcss-js@4.0.1(postcss@8.4.24):
|
||||
/postcss-js@4.0.1(postcss@8.4.28):
|
||||
resolution: {integrity: sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==}
|
||||
engines: {node: ^12 || ^14 || >= 16}
|
||||
peerDependencies:
|
||||
postcss: ^8.4.21
|
||||
dependencies:
|
||||
camelcase-css: 2.0.1
|
||||
postcss: 8.4.24
|
||||
postcss: 8.4.28
|
||||
|
||||
/postcss-load-config@4.0.1(postcss@8.4.24)(ts-node@10.9.1):
|
||||
/postcss-load-config@4.0.1(postcss@8.4.28)(ts-node@10.9.1):
|
||||
resolution: {integrity: sha512-vEJIc8RdiBRu3oRAI0ymerOn+7rPuMvRXslTvZUKZonDHFIczxztIyJ1urxM1x9JXEikvpWWTUUqal5j/8QgvA==}
|
||||
engines: {node: '>= 14'}
|
||||
peerDependencies:
|
||||
|
|
@ -6294,17 +6284,17 @@ packages:
|
|||
optional: true
|
||||
dependencies:
|
||||
lilconfig: 2.1.0
|
||||
postcss: 8.4.24
|
||||
postcss: 8.4.28
|
||||
ts-node: 10.9.1(@types/node@20.4.7)(typescript@5.2.2)
|
||||
yaml: 2.3.1
|
||||
|
||||
/postcss-nested@6.0.1(postcss@8.4.24):
|
||||
/postcss-nested@6.0.1(postcss@8.4.28):
|
||||
resolution: {integrity: sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==}
|
||||
engines: {node: '>=12.0'}
|
||||
peerDependencies:
|
||||
postcss: ^8.2.14
|
||||
dependencies:
|
||||
postcss: 8.4.24
|
||||
postcss: 8.4.28
|
||||
postcss-selector-parser: 6.0.13
|
||||
|
||||
/postcss-selector-parser@6.0.13:
|
||||
|
|
@ -6967,16 +6957,16 @@ packages:
|
|||
resolution: {integrity: sha512-3mFKyCo/MBcgyOTlrY8T7odzZFx+w+qKSMAmdFzRvqBfLlSigU6TZnlFHK0lkMwj9Bj8OYU+9yW9lmGuS0QEnQ==}
|
||||
dev: true
|
||||
|
||||
/tailwindcss-animate@1.0.6(tailwindcss@3.3.2):
|
||||
/tailwindcss-animate@1.0.6(tailwindcss@3.3.3):
|
||||
resolution: {integrity: sha512-4WigSGMvbl3gCCact62ZvOngA+PRqhAn7si3TQ3/ZuPuQZcIEtVap+ENSXbzWhpojKB8CpvnIsrwBu8/RnHtuw==}
|
||||
peerDependencies:
|
||||
tailwindcss: '>=3.0.0 || insiders'
|
||||
dependencies:
|
||||
tailwindcss: 3.3.2(ts-node@10.9.1)
|
||||
tailwindcss: 3.3.3(ts-node@10.9.1)
|
||||
dev: false
|
||||
|
||||
/tailwindcss@3.3.2(ts-node@10.9.1):
|
||||
resolution: {integrity: sha512-9jPkMiIBXvPc2KywkraqsUfbfj+dHDb+JPWtSJa9MLFdrPyazI7q6WX2sUrm7R9eVR7qqv3Pas7EvQFzxKnI6w==}
|
||||
/tailwindcss@3.3.3(ts-node@10.9.1):
|
||||
resolution: {integrity: sha512-A0KgSkef7eE4Mf+nKJ83i75TMyq8HqY3qmFIJSWy8bNt0v1lG7jUcpGpoTFxAwYcWOphcTBLPPJg+bDfhDf52w==}
|
||||
engines: {node: '>=14.0.0'}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
|
|
@ -6985,7 +6975,7 @@ packages:
|
|||
chokidar: 3.5.3
|
||||
didyoumean: 1.2.2
|
||||
dlv: 1.1.3
|
||||
fast-glob: 3.3.0
|
||||
fast-glob: 3.3.1
|
||||
glob-parent: 6.0.2
|
||||
is-glob: 4.0.3
|
||||
jiti: 1.19.3
|
||||
|
|
@ -6994,13 +6984,12 @@ packages:
|
|||
normalize-path: 3.0.0
|
||||
object-hash: 3.0.0
|
||||
picocolors: 1.0.0
|
||||
postcss: 8.4.24
|
||||
postcss-import: 15.1.0(postcss@8.4.24)
|
||||
postcss-js: 4.0.1(postcss@8.4.24)
|
||||
postcss-load-config: 4.0.1(postcss@8.4.24)(ts-node@10.9.1)
|
||||
postcss-nested: 6.0.1(postcss@8.4.24)
|
||||
postcss: 8.4.28
|
||||
postcss-import: 15.1.0(postcss@8.4.28)
|
||||
postcss-js: 4.0.1(postcss@8.4.28)
|
||||
postcss-load-config: 4.0.1(postcss@8.4.28)(ts-node@10.9.1)
|
||||
postcss-nested: 6.0.1(postcss@8.4.28)
|
||||
postcss-selector-parser: 6.0.13
|
||||
postcss-value-parser: 4.2.0
|
||||
resolve: 1.22.4
|
||||
sucrase: 3.34.0
|
||||
transitivePeerDependencies:
|
||||
|
|
@ -7205,7 +7194,7 @@ packages:
|
|||
execa: 5.1.1
|
||||
globby: 11.1.0
|
||||
joycon: 3.1.1
|
||||
postcss-load-config: 4.0.1(postcss@8.4.24)(ts-node@10.9.1)
|
||||
postcss-load-config: 4.0.1(postcss@8.4.28)(ts-node@10.9.1)
|
||||
resolve-from: 5.0.0
|
||||
rollup: 3.28.1
|
||||
source-map: 0.8.0-beta.0
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user