test: floating text selection toolbar
This commit is contained in:
@@ -710,12 +710,47 @@ function MorePopover({
|
|||||||
function FloatingToolbar({
|
function FloatingToolbar({
|
||||||
position,
|
position,
|
||||||
actions,
|
actions,
|
||||||
|
isMobile,
|
||||||
}: {
|
}: {
|
||||||
position: Position;
|
position: Position;
|
||||||
actions: ToolbarAction[];
|
actions: ToolbarAction[];
|
||||||
|
isMobile: boolean;
|
||||||
}) {
|
}) {
|
||||||
// Calculate position — center above the selection, clamp to viewport
|
if (isMobile) {
|
||||||
const toolbarWidth = actions.length * 44 + 8; // approximate
|
// Mobile: fixed bottom bar
|
||||||
|
return createPortal(
|
||||||
|
<div
|
||||||
|
className="fixed z-80 bottom-0 inset-x-0 border-t border-white/10 bg-black shadow-2xl px-3 py-2.5 pb-[max(0.75rem,env(safe-area-inset-bottom))] animate-in fade-in-0 slide-in-from-bottom-4 dark:bg-[#1a1a1a] dark:border-white/15"
|
||||||
|
onMouseDown={(e) => e.preventDefault()}
|
||||||
|
>
|
||||||
|
<div className="flex items-center justify-around gap-1">
|
||||||
|
{actions.map((action) => (
|
||||||
|
<button
|
||||||
|
key={action.key}
|
||||||
|
onClick={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
action.onClick();
|
||||||
|
}}
|
||||||
|
onMouseDown={(e) => e.preventDefault()}
|
||||||
|
className={cn(
|
||||||
|
"flex flex-col items-center gap-1 px-3 py-2 rounded-lg text-xs font-medium transition-colors min-w-14",
|
||||||
|
action.className ??
|
||||||
|
"text-white/70 active:bg-white/10 active:text-white",
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{action.icon}
|
||||||
|
<span>{action.label}</span>
|
||||||
|
</button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>,
|
||||||
|
document.body,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Desktop: floating above the selection
|
||||||
|
const toolbarWidth = actions.length * 44 + 8;
|
||||||
const left = Math.max(
|
const left = Math.max(
|
||||||
8,
|
8,
|
||||||
Math.min(
|
Math.min(
|
||||||
@@ -727,9 +762,9 @@ function FloatingToolbar({
|
|||||||
|
|
||||||
return createPortal(
|
return createPortal(
|
||||||
<div
|
<div
|
||||||
className="fixed z-80 flex items-center gap-0.5 rounded-xl border border-white/10 bg-black shadow-2xl px-1.5 py-1 animate-in fade-in-0 zoom-in-95 slide-in-from-bottom-2 dark:bg-[#1a1a1a] dark:border-white/15"
|
className="fixed z-80 flex items-center gap-1 rounded-xl border border-white/10 bg-black shadow-2xl px-2 py-1.5 animate-in fade-in-0 zoom-in-95 slide-in-from-bottom-2 dark:bg-[#1a1a1a] dark:border-white/15"
|
||||||
style={{ left, top }}
|
style={{ left, top }}
|
||||||
onMouseDown={(e) => e.preventDefault()} // prevent losing selection
|
onMouseDown={(e) => e.preventDefault()}
|
||||||
>
|
>
|
||||||
{actions.map((action) => (
|
{actions.map((action) => (
|
||||||
<button
|
<button
|
||||||
@@ -741,14 +776,14 @@ function FloatingToolbar({
|
|||||||
}}
|
}}
|
||||||
onMouseDown={(e) => e.preventDefault()}
|
onMouseDown={(e) => e.preventDefault()}
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex items-center gap-1.5 px-2.5 py-1.5 rounded-md text-xs font-medium transition-colors",
|
"flex items-center gap-1.5 px-3 py-2 rounded-lg text-sm font-medium transition-colors",
|
||||||
action.className ??
|
action.className ??
|
||||||
"text-white/70 hover:bg-white/10 hover:text-white",
|
"text-white/70 hover:bg-white/10 hover:text-white",
|
||||||
)}
|
)}
|
||||||
title={action.label}
|
title={action.label}
|
||||||
>
|
>
|
||||||
{action.icon}
|
{action.icon}
|
||||||
<span className="hidden sm:inline">{action.label}</span>
|
<span>{action.label}</span>
|
||||||
</button>
|
</button>
|
||||||
))}
|
))}
|
||||||
</div>,
|
</div>,
|
||||||
@@ -1008,7 +1043,11 @@ export function TextSelectionToolbar() {
|
|||||||
return (
|
return (
|
||||||
<div data-selection-toolbar>
|
<div data-selection-toolbar>
|
||||||
{/* Floating toolbar */}
|
{/* Floating toolbar */}
|
||||||
<FloatingToolbar position={toolbarPos} actions={toolbarActions} />
|
<FloatingToolbar
|
||||||
|
position={toolbarPos}
|
||||||
|
actions={toolbarActions}
|
||||||
|
isMobile={isMobile}
|
||||||
|
/>
|
||||||
|
|
||||||
{/* More popover */}
|
{/* More popover */}
|
||||||
<MorePopover
|
<MorePopover
|
||||||
|
|||||||
Reference in New Issue
Block a user