feat(resource-details): make copy fields visible and accessible

This commit is contained in:
Andras Bacsai 2026-06-15 13:17:53 +02:00
parent d2deaa8363
commit dfd4d7e802
3 changed files with 65 additions and 18 deletions

View file

@ -2,24 +2,27 @@
<div class="w-full" x-data="{ copied: false, isSecure: window.isSecureContext }">
@if ($label)
<label class="flex gap-1 items-center mb-1 text-sm font-medium">{{ $label }}</label>
<label class="flex gap-1 items-center mb-1 text-sm font-medium text-black dark:text-white">{{ $label }}</label>
@endif
<div class="relative">
<input type="text" value="{{ $text }}" class="input pr-10"
<input type="text" value="{{ $text }}"
class="input pr-11 bg-white dark:bg-coolgray-100 dark:read-only:bg-coolgray-100 dark:read-only:text-white"
readonly
@keydown.prevent @paste.prevent @cut.prevent @drop.prevent
@focus="$event.target.select()">
<button
x-show="isSecure"
@click.prevent="copied = true; navigator.clipboard.writeText({{ Js::from($text) }}); setTimeout(() => copied = false, 1000)"
class="absolute right-2 top-1/2 -translate-y-1/2 p-1.5 text-gray-400 hover:text-gray-300 transition-colors"
title="Copy to clipboard">
<svg x-show="!copied" class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z" />
</svg>
<svg x-show="copied" class="w-5 h-5 text-green-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7" />
</svg>
</button>
<button
x-show="isSecure"
@click.prevent="copied = true; navigator.clipboard.writeText({{ Js::from($text) }}); setTimeout(() => copied = false, 1000)"
class="absolute right-2 top-1/2 -translate-y-1/2 rounded-sm p-1.5 text-neutral-500 transition-colors hover:text-neutral-700 focus-visible:ring-2 focus-visible:ring-coollabs focus-visible:ring-offset-2 dark:text-neutral-400 dark:hover:text-white dark:focus-visible:ring-warning dark:focus-visible:ring-offset-base"
title="Copy to clipboard"
aria-label="Copy to clipboard">
<svg x-show="!copied" class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z" />
</svg>
<svg x-show="copied" class="w-5 h-5 text-green-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7" />
</svg>
</button>
</div>
</div>

View file

@ -1,6 +1,4 @@
<div class="w-full max-h-[70vh] overflow-y-auto pr-1 -mt-4">
<div class="pb-4 text-sm dark:text-neutral-400">Identifiers for this resource. Read-only</div>
<div class="w-full max-h-[70vh] overflow-y-auto pr-1 pt-1">
<div class="flex flex-col gap-6">
<div>
<h3>Resource</h3>

View file

@ -0,0 +1,46 @@
<?php
use Illuminate\Support\Facades\Blade;
use Illuminate\Support\MessageBag;
use Illuminate\Support\ViewErrorBag;
beforeEach(function () {
$errors = new ViewErrorBag;
$errors->put('default', new MessageBag);
view()->share('errors', $errors);
});
it('keeps the resource details helper text visible below the modal header', function () {
$html = view('livewire.project.shared.resource-details', [
'resource' => (object) [
'name' => 'Crash Loop Example',
'uuid' => 'crashloop',
],
'environment_uuid' => null,
'environment_name' => null,
'project_uuid' => null,
'project_name' => null,
'server_uuid' => null,
'server_name' => null,
'stack_applications' => [],
'stack_databases' => [],
])->render();
expect($html)
->toContain('Identifiers for this resource. Read-only')
->toContain('pt-1')
->not->toContain('-mt-4');
});
it('renders copy fields as visible readonly controls with an accessible copy action', function () {
$html = Blade::render('<x-forms.copy-button label="UUID" text="crashloop" />');
expect($html)
->toContain('label class="flex gap-1 items-center mb-1 text-sm font-medium text-black dark:text-white"')
->toContain('readonly')
->toContain('class="input pr-11 bg-white dark:bg-coolgray-100 dark:read-only:bg-coolgray-100 dark:read-only:text-white"')
->toContain('aria-label="Copy to clipboard"')
->toContain('title="Copy to clipboard"')
->toContain('rounded-sm p-1.5 text-neutral-500 transition-colors hover:text-neutral-700 focus-visible:ring-2 focus-visible:ring-coollabs focus-visible:ring-offset-2 dark:text-neutral-400 dark:hover:text-white dark:focus-visible:ring-warning dark:focus-visible:ring-offset-base')
->toContain('class="w-5 h-5 text-green-500"');
});