fix(files): responsive file rows + restore button cursor (v0.9.55)

- File manager: on tablet widths the lg table grid squeezed the name column
  (minmax(0,1fr)) to near-zero behind the perms/size/modified columns + wide
  action buttons, so the filename was unreadable/overlapped. The rows now render
  as a stacked card below xl — name on its own full-width line, a folded
  perms·size·modified line and the actions beneath — and only switch to the
  table grid at xl (tightened columns). Mobile tidied up to match.
- Restore the pointer cursor: Tailwind v4's preflight makes buttons use the
  default cursor, so clickable controls (folder names, every button) didn't show
  a hand. Added a base rule giving enabled button/[role=button]/summary/label
  the pointer cursor.

Verified the row at desktop / tablet / mobile widths (name readable at every
breakpoint, table only when wide). 374 tests pass (the Livewire test renders the
blade), Tailwind build clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
feat/v1-foundation v0.9.55
boban 2026-06-22 06:06:32 +02:00
parent 359aa86aea
commit 8914f5f746
4 changed files with 37 additions and 20 deletions

View File

@ -13,7 +13,17 @@ getaggte Releases (Kanal `stable`, optional `beta`) — niemals Entwicklungs-Bui
_Keine offenen Änderungen — der nächste Stand wird hier gesammelt und als `vX.Y.Z` getaggt._
## [0.9.54] - 2026-06-22
## [0.9.55] - 2026-06-22
### Behoben
- **Datei-Manager: Dateiname im Tablet-Modus vom Rechte-Block überdeckt.** Die Tabellenspalten
(Rechte/Größe/Geändert) + Aktions-Buttons quetschten die Namensspalte auf nahezu null. Die Liste
rendert jetzt **unterhalb großer Bildschirme als gestapelte Karte** (Name in voller Breite, Meta-Zeile
und Aktionen darunter); die Tabellenansicht erscheint erst auf breiten Displays. Die mobile Ansicht
wurde dabei mit aufgeräumt.
- **Zeiger-Cursor auf Buttons fehlte.** Tailwind v4 stellt Buttons standardmäßig auf den
Standard-Cursor; auf anklickbaren Elementen (z. B. Ordnernamen, alle Buttons) erscheint jetzt wieder
der Hand-Zeiger.
### Behoben
- **Datei-Manager: „undefined is not valid JSON" beim Öffnen mancher Dateien.** Öffnete man eine

View File

@ -2,7 +2,7 @@
return [
// First tagged release is v0.1.0 (semantic, not -dev).
'version' => '0.9.54',
'version' => '0.9.55',
// Deployed commit + branch. install.sh bakes these into .env from the host's .git (the prod
// image ships no .git); the Versions page prefers them and falls back to a live .git read in

View File

@ -112,6 +112,15 @@
color-scheme: dark;
}
/* Tailwind v4's preflight makes buttons use the default cursor restore the pointer on
enabled interactive controls so clickable elements feel clickable (e.g. folder names). */
button:not(:disabled),
[role="button"]:not([aria-disabled="true"]),
summary,
label[for] {
cursor: pointer;
}
/* keyboard focus — visible token ring on the dark UI (a11y) */
:focus-visible {
outline: 2px solid var(--color-accent);

View File

@ -57,8 +57,8 @@
</label>
</x-slot:actions>
{{-- Column header (desktop only) --}}
<div class="hidden border-b border-line px-4 py-2 sm:px-5 lg:grid lg:grid-cols-[minmax(0,1fr)_8rem_6rem_11rem_auto] lg:items-center lg:gap-4">
{{-- Column header (wide desktop only below xl the rows render as stacked cards) --}}
<div class="hidden border-b border-line px-4 py-2 sm:px-5 xl:grid xl:grid-cols-[minmax(0,1fr)_7rem_5rem_10rem_auto] xl:items-center xl:gap-4">
<span class="font-mono text-[10px] uppercase tracking-wider text-ink-4">{{ __('files.col_name') }}</span>
<span class="font-mono text-[10px] uppercase tracking-wider text-ink-4">{{ __('files.col_perms') }}</span>
<span class="text-right font-mono text-[10px] uppercase tracking-wider text-ink-4">{{ __('files.col_size') }}</span>
@ -72,7 +72,7 @@
<div class="flex items-center gap-3 px-4 py-3 sm:px-5">
<x-skeleton class="h-8 w-8 rounded-sm" />
<x-skeleton class="h-3 w-48 max-w-full" />
<x-skeleton class="ml-auto hidden h-3 w-24 lg:block" />
<x-skeleton class="ml-auto hidden h-3 w-24 xl:block" />
</div>
@endfor
@else
@ -80,8 +80,10 @@
@php $isDir = $e['type'] === 'dir'; @endphp
{{-- Stable wire:key per row: without it Livewire's morph clones nodes by position and
the inline Alpine x-data (modalTrigger) loses its scope "pending is not defined". --}}
{{-- Below xl: a stacked card (name on its own full-width line, meta + actions beneath) so
the filename is never squeezed by the meta/action columns. xl+: a real table grid. --}}
<div wire:key="fe-{{ md5($e['type'].'/'.$e['name']) }}"
class="group grid grid-cols-1 gap-x-4 gap-y-2 px-4 py-3 transition-colors hover:bg-raised sm:px-5 lg:grid-cols-[minmax(0,1fr)_8rem_6rem_11rem_auto] lg:items-center">
class="group px-4 py-3 transition-colors hover:bg-raised sm:px-5 xl:grid xl:grid-cols-[minmax(0,1fr)_7rem_5rem_10rem_auto] xl:items-center xl:gap-4">
{{-- Name + icon (directories look clickable) --}}
<div class="flex min-w-0 items-center gap-3">
<span @class([
@ -94,7 +96,7 @@
@if ($isDir)
<button type="button" wire:click="open({{ $loop->index }})" class="min-w-0 flex-1 text-left">
<span class="truncate font-mono text-sm text-ink group-hover:text-accent-text">{{ $e['name'] }}/</span>
<span class="block truncate font-mono text-sm text-ink group-hover:text-accent-text">{{ $e['name'] }}/</span>
</button>
@else
{{-- Filename opens the editor modal too inline modalTrigger keeps the
@ -110,26 +112,22 @@
@endif
</div>
{{-- Permissions (hidden on mobile; shown inline below name on tablet+) --}}
<p class="hidden font-mono text-xs text-ink-3 lg:block">{{ $e['perms'] }}</p>
{{-- Meta as real table cells (xl only) --}}
<p class="hidden truncate font-mono text-xs text-ink-3 xl:block">{{ $e['perms'] }}</p>
<p class="hidden font-mono text-xs text-ink-3 xl:block xl:text-right">{{ $fmtSize($e['size']) }}</p>
<p class="hidden truncate font-mono text-xs text-ink-3 xl:block">{{ $e['modified'] }}</p>
{{-- Size (hidden on mobile) --}}
<p class="hidden font-mono text-xs text-ink-3 sm:block lg:text-right">{{ $fmtSize($e['size']) }}</p>
{{-- Modified --}}
<p class="hidden font-mono text-xs text-ink-3 sm:block">{{ $e['modified'] }}</p>
{{-- Compact meta line for mobile (perms · size · modified) --}}
<p class="flex flex-wrap items-center gap-x-2 font-mono text-[11px] text-ink-4 sm:hidden">
{{-- Folded meta line under the name (mobile + tablet) --}}
<p class="mt-1.5 flex flex-wrap items-center gap-x-2 gap-y-0.5 pl-11 font-mono text-[11px] text-ink-4 xl:hidden">
<span>{{ $e['perms'] }}</span>
<span>·</span>
<span class="opacity-50">·</span>
<span>{{ $fmtSize($e['size']) }}</span>
<span>·</span>
<span class="opacity-50">·</span>
<span>{{ $e['modified'] }}</span>
</p>
{{-- Row actions --}}
<div class="flex shrink-0 items-center gap-1 lg:justify-end">
<div class="mt-2.5 flex flex-wrap items-center gap-1.5 pl-11 xl:mt-0 xl:justify-end xl:gap-1 xl:pl-0">
@unless ($isDir)
<x-btn variant="secondary" wire:click="download({{ $loop->index }})">{{ __('files.download') }}</x-btn>
<x-modal-trigger variant="secondary" action="edit({{ $loop->index }})">{{ __('common.edit') }}</x-modal-trigger>