uui
blocksora-theme-pickersource: ok · hit
Sora Theme Picker
npx shadcn add "https://uui.app/r/sora-theme-picker.json"free
No selection tags yet — empty means no evidence, not lack of support.
Files2 · source cached 10/15/2026, 1:55:48 AM
components/uui/sora-theme-picker/dropdown-menu.tsx
'use client';
import * as React from 'react';
import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';
import { CheckIcon, ChevronRightIcon } from 'lucide-react';
import { cn } from '@/lib/utils';
function DropdownMenu({ ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.Root>) {
return <DropdownMenuPrimitive.Root data-slot="dropdown-menu" {...props} />;
}
function DropdownMenuPortal({ ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.Portal>) {
return <DropdownMenuPrimitive.Portal data-slot="dropdown-menu-portal" {...props} />;
}
function DropdownMenuTrigger({ ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.Trigger>) {
return <DropdownMenuPrimitive.Trigger data-slot="dropdown-menu-trigger" {...props} />;
}
function DropdownMenuContent({ className, sideOffset = 4, ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.Content>) {
return (
<DropdownMenuPrimitive.Portal>
<DropdownMenuPrimitive.Content
data-slot="dropdown-menu-content"
sideOffset={sideOffset}
className={cn(
'z-50 min-w-32 rounded-2xl border bg-popover/98 backdrop-blur-xl saturate-200 p-1.5 text-popover-foreground shadow-2xl focus:outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
className,
)}
{...props}
/>
</DropdownMenuPrimitive.Portal>
);
}
function DropdownMenuGroup({ ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.Group>) {
return <DropdownMenuPrimitive.Group data-slot="dropdown-menu-group" {...props} />;
}
function DropdownMenuItem({
className,
inset,
...props
}: React.ComponentProps<typeof DropdownMenuPrimitive.Item> & {
inset?: boolean;
}) {
return (
<DropdownMenuPrimitive.Item
data-slot="dropdown-menu-item"
data-inset={inset}
className={cn(
'data-highlighted:bg-accent data-highlighted:text-accent-foreground relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-disabled:pointer-events-none data-disabled:opacity-50',
inset && 'pl-8',
className,
)}
{...props}
/>
);
}
function DropdownMenuCheckboxItem({ className, children, checked, ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.CheckboxItem>) {
return (
<DropdownMenuPrimitive.CheckboxItem
className={cn(
'data-highlighted:bg-accentata-[highlighted]:text-accent-foreground relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none data-disabled:pointer-events-none data-disabled:opacity-50',
className,
)}
checked={checked}
{...props}
>
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
<DropdownMenuPrimitive.ItemIndicator>
<CheckIcon className="h-4 w-4" />
</DropdownMenuPrimitive.ItemIndicator>
</span>
{children}
</DropdownMenuPrimitive.CheckboxItem>
);
}
function DropdownMenuRadioGroup({ ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.RadioGroup>) {
return <DropdownMenuPrimitive.RadioGroup data-slot="dropdown-menu-radio-group" {...props} />;
}
function DropdownMenuRadioItem({ className, children, ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.RadioItem>) {
return (
<DropdownMenuPrimitive.RadioItem
data-slot="dropdown-menu-radio-item"
className={cn(
'group relative flex w-full cursor-pointer select-none items-center justify-between gap-2 rounded-[13px] px-2 py-2.5 text-sm outline-none data-disabled:pointer-events-noneata-[disabled]:cursor-default data-highlighted:bg-foreground/10 data-highlighted:text-accent-foreground focus:bg-foreground/10 data-disabled:opacity-50',
className,
)}
{...props}
>
{children}
<span className="flex h-3.5 w-3.5 items-center justify-center">
<div className="flex h-4 w-4 shrink-0 items-center justify-center rounded-full border border-accent/15 group-data-[state=checked]:border-foreground group-data-[state=checked]:ring-4 group-data-[state=checked]:ring-inset group-data-[state=checked]:ring-foreground" />
</span>
</DropdownMenuPrimitive.RadioItem>
);
}
function DropdownMenuLabel({
className,
inset,
...props
}: React.ComponentProps<typeof DropdownMenuPrimitive.Label> & {
inset?: boolean;
}) {
return <DropdownMenuPrimitive.Label data-slot="dropdown-menu-label" data-inset={inset} className={cn('px-2 py-1.5 text-sm font-semibold', inset && 'pl-8', className)} {...props} />;
}
function DropdownMenuSeparator({ className, ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.Separator>) {
return <DropdownMenuPrimitive.Separator data-slot="dropdown-menu-separator" className={cn('bg-muted -mx-1 my-1 h-px', className)} {...props} />;
}
function DropdownMenuShortcut({ className, ...props }: React.ComponentProps<'span'>) {
return <span data-slot="dropdown-menu-shortcut" className={cn('ml-auto text-xs tracking-widest opacity-60', className)} {...props} />;
}
function DropdownMenuSub({ ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.Sub>) {
return <DropdownMenuPrimitive.Sub data-slot="dropdown-menu-sub" {...props} />;
}
function DropdownMenuSubTrigger({
className,
inset,
children,
...props
}: React.ComponentProps<typeof DropdownMenuPrimitive.SubTrigger> & {
inset?: boolean;
}) {
return (
<DropdownMenuPrimitive.SubTrigger
data-slot="dropdown-menu-sub-trigger"
data-inset={inset}
className={cn(
'data-highlighted:bg-accent data-[state=open]:bg-accent data-highlighted:text-accent-foreground data-[state=open]:text-accent-foreground flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none',
inset && 'pl-8',
className,
)}
{...props}
>
{children}
<ChevronRightIcon className="ml-auto h-4 w-4" />
</DropdownMenuPrimitive.SubTrigger>
);
}
function DropdownMenuSubContent({ className, ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.SubContent>) {
return (
<DropdownMenuPrimitive.SubContent
data-slot="dropdown-menu-sub-content"
className={cn(
'z-50 min-w-32 overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg focus:outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
className,
)}
{...props}
/>
);
}
export {
DropdownMenu,
DropdownMenuPortal,
DropdownMenuTrigger,
DropdownMenuContent,
DropdownMenuGroup,
DropdownMenuItem,
DropdownMenuCheckboxItem,
DropdownMenuRadioGroup,
DropdownMenuRadioItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuShortcut,
DropdownMenuSub,
DropdownMenuSubTrigger,
DropdownMenuSubContent,
};
components/uui/sora-theme-picker/example.tsx
'use client';
import { ChevronDownIcon, MonitorIcon, MoonIcon, PaintbrushVerticalIcon, SunIcon, UserIcon } from 'lucide-react';
import { DropdownMenu, DropdownMenuContent, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuTrigger } from './dropdown-menu';
import { useState } from 'react';
export function ThemePicker() {
const [selectedTheme, setSelectedTheme] = useState('system');
return (
<div className="h-svh flex items-center justify-center px-4">
<div className="w-full mx-auto max-w-sm space-y-2 py-2 px-4 border rounded-2xl">
<div className="flex h-10 items-center">
<div className="flex w-3/5 items-center gap-1">
<UserIcon className="w-4" />
<h2>Username</h2>
</div>
<div className="w-2/5 min-w-0">MagicalAurora</div>
</div>
<div className="flex h-10 items-center">
<div className="flex w-3/5 items-center gap-1">
<PaintbrushVerticalIcon className="w-4" />
<h2>Theme</h2>
</div>
<div className="w-2/5 min-w-0">
<DropdownMenu>
<DropdownMenuTrigger className="flex w-full items-center gap-1 text-start">
{selectedTheme[0].toUpperCase() + selectedTheme.slice(1)}
<ChevronDownIcon className="w-4" />
</DropdownMenuTrigger>
<DropdownMenuContent className="max-w-52 w-52">
<DropdownMenuRadioGroup value={selectedTheme} onValueChange={setSelectedTheme}>
<DropdownMenuRadioItem value="system">
<div className="flex items-center gap-2">
<MonitorIcon className="w-5" />
System
</div>
</DropdownMenuRadioItem>
<DropdownMenuRadioItem value="light">
<div className="flex items-center gap-2">
<SunIcon className="w-5" />
Light
</div>
</DropdownMenuRadioItem>
<DropdownMenuRadioItem value="dark" className="flex items-center gap-2">
<div className="flex items-center gap-2">
<MoonIcon className="mr-0.5 w-[18px]" />
Dark
</div>
</DropdownMenuRadioItem>
</DropdownMenuRadioGroup>
</DropdownMenuContent>
</DropdownMenu>
</div>
</div>
</div>
</div>
);
}