RDS/Patterns

Patterns

Reusable interaction patterns assembled from RDS primitives — copy them directly into your project and customize for your context.

CompositionInteractiveCopy-paste
01Combobox
02Confirmation Dialog
03Settings Rows

Receive stream milestone alerts via email

A summary of your analytics every Monday

Get notified when artists request to collaborate

04Data Table with Selection
TitleDurationStreamsStatus
Midnight Drive3:2412.4k
Live
Coastal Haze4:018.7k
Live
Undertow2:585.1k
Draft
Signals3:47
Draft
05Upload Dropzone

Drop audio file here

MP3, WAV, FLAC up to 500 MB

Usage note

Drop a file onto the demo above to see the upload progress state. Wire onDrop to your upload handler — pairs well with react-dropzone for advanced features like MIME validation.

06Inline Edit
07Date Picker
import { useState } from "react"import { format } from "date-fns"import { Calendar } from "@/components/ui/calendar"import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"import { Button } from "@/components/ui/button"import { CalendarIcon } from "lucide-react"export function DatePicker() {  const [date, setDate] = useState<Date>()  return (    <Popover>      <PopoverTrigger asChild>        <Button variant="outline" className="w-48 justify-start text-left font-normal">          <CalendarIcon className="mr-2 h-4 w-4" />          {date ? format(date, "PPP") : <span className="text-muted-foreground">Pick a date</span>}        </Button>      </PopoverTrigger>      <PopoverContent className="w-auto p-0">        <Calendar mode="single" selected={date} onSelect={setDate} initialFocus />      </PopoverContent>    </Popover>  )}
08Toast Notifications
// 1. Add <Toaster /> once to your root layoutimport { Toaster } from "@/components/ui/sonner"export default function RootLayout({ children }) {  return (    <html>      <body>        {children}        <Toaster />      </body>    </html>  )}// 2. Call toast() anywhere in a client componentimport { toast } from "sonner"// Successtoast.success("Release published", {  description: "Midnight Drive is now live on all platforms.",})// Errortoast.error("Upload failed", {  description: "The file exceeds the 500 MB limit.",})// Loading + resolveconst id = toast.loading("Publishing release…")await publishRelease()toast.success("Published!", { id })
10Filter Bar
11Content Grid

Midnight Drive

Live

Lena Rhodes

41.2k streams

Static Rain

Live

Fort Echo

28.7k streams

Neon Hollow

Draft

Lena Rhodes

streams

13Tabbed Page

Midnight Drive

by Lena Rhodes · 41.2k streams

Live

Streams

41.2k

Saves

3.8k

Shares

912

14Empty State

No releases yet

Upload your first release to start tracking streams and revenue.

15List Item
LR

Lena Rhodes

Indie Soul

41.2k
FE

Fort Echo

Electronic

28.7k
SP

Sienna Park

R&B

19.4k
MD

Moku Drift

Lo-fi

14.1k
16Full Page Composition
export default function ReleasesPage() {  return (    <div className="space-y-6">      {/* 09 — Page header */}      <div className="space-y-1">        <nav className="flex items-center gap-1 text-sm text-muted-foreground">          <Link href="/">Catalog</Link>          <ChevronRight className="h-3.5 w-3.5" />          <span className="text-foreground">Releases</span>        </nav>        <div className="flex items-start justify-between gap-4">          <h1 className="text-2xl font-semibold tracking-tight">Releases</h1>          <Button><Plus /> Add Release</Button>        </div>      </div>      <Separator />      {/* 10 — Filter bar */}      <div className="flex flex-wrap items-center gap-3">        <div className="relative flex-1 min-w-50">          <Search className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" />          <Input className="pl-9" placeholder="Search releases..." />        </div>        <Select><SelectTrigger className="w-35"><SelectValue placeholder="Status" /></SelectTrigger>...</Select>      </div>      {/* 11 — Content grid (or empty state) */}      {releases.length === 0 ? (        <EmptyState />      ) : (        <div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">          {releases.map((r) => <ReleaseCard key={r.id} release={r} />)}        </div>      )}    </div>  )}