Fix guest URL editing inconsistencies: unify icons and use Portal for popover

This commit is contained in:
rcourtman
2025-12-30 20:09:58 +00:00
parent 0caf39456d
commit 421ddf027a
2 changed files with 60 additions and 61 deletions
@@ -354,11 +354,7 @@ export const DockerHostSummaryTable: Component<DockerHostSummaryTableProps> = (p
onClick={(e) => handleStartEditingUrl(summary.host.id, e)}
>
<svg class="w-3 h-3" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<Show when={getHostCustomUrl(summary.host.id)} fallback={
<path stroke-linecap="round" stroke-linejoin="round" d="M12 4v16m8-8H4" />
}>
<path stroke-linecap="round" stroke-linejoin="round" d="M15.232 5.232l3.536 3.536m-2.036-5.036a2.5 2.5 0 113.536 3.536L6.5 21.036H3v-3.572L16.732 3.732z" />
</Show>
<path stroke-linecap="round" stroke-linejoin="round" d="M15.232 5.232l3.536 3.536m-2.036-5.036a2.5 2.5 0 113.536 3.536L6.5 21.036H3v-3.572L16.732 3.732z" />
</svg>
</button>
<Show when={getDisplayName(summary.host) !== summary.host.hostname}>
@@ -1,4 +1,5 @@
import { Component, Show, createSignal, createEffect } from 'solid-js';
import { Portal } from 'solid-js/web';
export interface UrlEditPopoverProps {
/** Whether the popover is visible */
@@ -57,72 +58,74 @@ export const UrlEditPopover: Component<UrlEditPopoverProps> = (props) => {
return (
<Show when={props.isOpen && props.position}>
<div
data-url-editor
class="fixed z-[9999] bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg shadow-xl p-3 min-w-[300px]"
style={{ top: `${props.position!.top}px`, left: `${props.position!.left}px` }}
onClick={(e) => e.stopPropagation()}
>
<div class="flex items-center gap-2">
<input
ref={inputRef}
type="url"
class="flex-1 text-sm px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-colors"
placeholder={props.placeholder ?? 'https://example.com'}
value={props.value}
onInput={(e) => props.onValueChange(e.currentTarget.value)}
onKeyDown={handleKeyDown}
disabled={props.isSaving}
/>
<Portal mount={document.body}>
<div
data-url-editor
class="fixed z-[9999] bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg shadow-xl p-3 min-w-[300px]"
style={{ top: `${props.position!.top}px`, left: `${props.position!.left}px` }}
onClick={(e) => e.stopPropagation()}
>
<div class="flex items-center gap-2">
<input
ref={inputRef}
type="url"
class="flex-1 text-sm px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-colors"
placeholder={props.placeholder ?? 'https://example.com'}
value={props.value}
onInput={(e) => props.onValueChange(e.currentTarget.value)}
onKeyDown={handleKeyDown}
disabled={props.isSaving}
/>
{/* Save button */}
<button
type="button"
class="p-2 text-green-600 hover:text-green-700 dark:text-green-400 dark:hover:text-green-300 hover:bg-green-50 dark:hover:bg-green-900/20 rounded transition-colors disabled:opacity-50"
title="Save (Enter)"
disabled={props.isSaving}
onClick={props.onSave}
>
<svg class="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7" />
</svg>
</button>
{/* Delete button - only show if there's an existing URL */}
<Show when={props.hasExistingUrl && props.onDelete}>
{/* Save button */}
<button
type="button"
class="p-2 text-red-500 hover:text-red-600 dark:text-red-400 dark:hover:text-red-300 hover:bg-red-50 dark:hover:bg-red-900/20 rounded transition-colors disabled:opacity-50"
title="Remove URL"
class="p-2 text-green-600 hover:text-green-700 dark:text-green-400 dark:hover:text-green-300 hover:bg-green-50 dark:hover:bg-green-900/20 rounded transition-colors disabled:opacity-50"
title="Save (Enter)"
disabled={props.isSaving}
onClick={props.onDelete}
onClick={props.onSave}
>
<svg class="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
<path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7" />
</svg>
</button>
{/* Delete button - only show if there's an existing URL */}
<Show when={props.hasExistingUrl && props.onDelete}>
<button
type="button"
class="p-2 text-red-500 hover:text-red-600 dark:text-red-400 dark:hover:text-red-300 hover:bg-red-50 dark:hover:bg-red-900/20 rounded transition-colors disabled:opacity-50"
title="Remove URL"
disabled={props.isSaving}
onClick={props.onDelete}
>
<svg class="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
</svg>
</button>
</Show>
{/* Cancel button */}
<button
type="button"
class="p-2 text-gray-500 hover:text-gray-600 dark:text-gray-400 dark:hover:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 rounded transition-colors"
title="Cancel (Esc)"
onClick={props.onCancel}
>
<svg class="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
</div>
{/* Help text */}
<Show when={props.helpText}>
<p class="mt-2 text-xs text-gray-500 dark:text-gray-400">
{props.helpText}
</p>
</Show>
{/* Cancel button */}
<button
type="button"
class="p-2 text-gray-500 hover:text-gray-600 dark:text-gray-400 dark:hover:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 rounded transition-colors"
title="Cancel (Esc)"
onClick={props.onCancel}
>
<svg class="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
</div>
{/* Help text */}
<Show when={props.helpText}>
<p class="mt-2 text-xs text-gray-500 dark:text-gray-400">
{props.helpText}
</p>
</Show>
</div>
</Portal>
</Show>
);
};