feat(desktop): long-press a rail profile to pick its color
Hold (~450ms) a profile square — or right-click → Color… — to open a shadcn Popover of swatches and override its rail color, with Auto to fall back to the deterministic hue. The hold timer rides alongside the dnd pointer listener (a real drag cancels it, the trailing click is suppressed), so reorder/select/recolor stay distinct gestures. Overrides persist in localStorage ($profileColors), resolved via resolveProfileColor (override wins, else the name-hashed hue). Cosmetic and gated on the multi-profile rail, so single-profile users are unaffected. Adds a reusable ui/popover.tsx (radix-ui umbrella).
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
import { Popover as PopoverPrimitive } from 'radix-ui'
|
||||
import * as React from 'react'
|
||||
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
function Popover({ ...props }: React.ComponentProps<typeof PopoverPrimitive.Root>) {
|
||||
return <PopoverPrimitive.Root data-slot="popover" {...props} />
|
||||
}
|
||||
|
||||
function PopoverTrigger({ ...props }: React.ComponentProps<typeof PopoverPrimitive.Trigger>) {
|
||||
return <PopoverPrimitive.Trigger data-slot="popover-trigger" {...props} />
|
||||
}
|
||||
|
||||
function PopoverAnchor({ ...props }: React.ComponentProps<typeof PopoverPrimitive.Anchor>) {
|
||||
return <PopoverPrimitive.Anchor data-slot="popover-anchor" {...props} />
|
||||
}
|
||||
|
||||
function PopoverContent({
|
||||
align = 'center',
|
||||
className,
|
||||
collisionPadding = 8,
|
||||
sideOffset = 6,
|
||||
...props
|
||||
}: React.ComponentProps<typeof PopoverPrimitive.Content>) {
|
||||
return (
|
||||
<PopoverPrimitive.Portal>
|
||||
<PopoverPrimitive.Content
|
||||
align={align}
|
||||
// Mirrors DropdownMenuContent: themed elevated surface, viewport-aware
|
||||
// (Radix flips/shifts off edges), with the standard open/close motion.
|
||||
className={cn(
|
||||
'z-50 w-72 origin-(--radix-popover-content-transform-origin) rounded-lg border border-(--ui-stroke-secondary) bg-[color-mix(in_srgb,var(--ui-bg-elevated)_96%,transparent)] p-2 text-popover-foreground shadow-md backdrop-blur-md outline-hidden data-[side=bottom]:slide-in-from-top-1 data-[side=left]:slide-in-from-right-1 data-[side=right]:slide-in-from-left-1 data-[side=top]:slide-in-from-bottom-1 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95',
|
||||
className
|
||||
)}
|
||||
collisionPadding={collisionPadding}
|
||||
data-slot="popover-content"
|
||||
sideOffset={sideOffset}
|
||||
{...props}
|
||||
/>
|
||||
</PopoverPrimitive.Portal>
|
||||
)
|
||||
}
|
||||
|
||||
export { Popover, PopoverAnchor, PopoverContent, PopoverTrigger }
|
||||
Reference in New Issue
Block a user