From 8fcff6ebd121475d1d47d0272d121bcce037827e Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Fri, 30 Oct 2026 16:14:46 +0100 Subject: [PATCH] fix(ui): consolidate table row actions into one menu pattern Rows with two or more actions use a shared "..." menu (x-table.row-actions); rows with one action keep a single icon button. Every actions column has an "Actions" header. Removing a member and revoking an invitation now ask for confirmation. Row and card icons are neutral in dark mode. Co-Authored-By: Claude Opus 5.5 --- resources/css/app.css | 39 ++-- .../shared-variables/editor.blade.php | 2 +- .../components/table/row-action.blade.php | 10 + .../components/table/row-actions.blade.php | 27 +++ .../views/livewire/admin/index.blade.php | 2 +- resources/views/livewire/dashboard.blade.php | 6 +- .../application/partials/domain-row.blade.php | 65 +++--- .../application/preview-domains.blade.php | 55 +++-- .../database/scheduled-backups.blade.php | 12 +- .../views/livewire/project/index.blade.php | 2 +- .../service/backup-executions.blade.php | 4 +- .../project/service/configuration.blade.php | 2 +- .../service/partials/domain-table.blade.php | 59 ++--- .../project/service/resource-card.blade.php | 34 +-- .../service/volume-backup/index.blade.php | 42 ++-- .../shared/environment-variable/all.blade.php | 2 +- .../show-hardcoded.blade.php | 2 +- .../environment-variable/show.blade.php | 2 +- .../project/shared/file-browser.blade.php | 121 ++++------ .../project/shared/storages/all.blade.php | 206 +++++++++++------- .../volume-backups/executions.blade.php | 23 +- .../views/livewire/project/show.blade.php | 2 +- .../livewire/security/api-tokens.blade.php | 37 +--- .../security/cloud-init-scripts.blade.php | 16 +- .../security/cloud-provider-tokens.blade.php | 16 +- .../security/integration-tokens.blade.php | 10 +- .../partials/api-token-fields.blade.php | 2 +- .../security/private-key/index.blade.php | 22 +- .../livewire/server/docker-images.blade.php | 16 +- .../server-registries.blade.php | 50 +++-- .../server/proxy/certificates.blade.php | 99 +++++---- .../views/livewire/server/resources.blade.php | 59 ++--- .../server/security/patches.blade.php | 2 +- .../livewire/storage/resources.blade.php | 55 +++-- .../views/livewire/team/admin-view.blade.php | 5 +- .../views/livewire/team/invitations.blade.php | 24 +- .../views/livewire/team/member.blade.php | 103 +++++---- tests/Feature/BackupNowAvailabilityTest.php | 2 +- ...bleLivewireComponentsAuthorizationTest.php | 4 +- .../PersistentStorageVolumesLayoutTest.php | 17 +- tests/Feature/ServiceResourceRoutingTest.php | 14 +- 41 files changed, 710 insertions(+), 562 deletions(-) create mode 100644 resources/views/components/table/row-action.blade.php create mode 100644 resources/views/components/table/row-actions.blade.php diff --git a/resources/css/app.css b/resources/css/app.css index 33cb50af21..1a8d0f0cba 100644 --- a/resources/css/app.css +++ b/resources/css/app.css @@ -2806,6 +2806,12 @@ html[data-theme="custom"]:not(.dark) :is(.application-settings-section, .applica background: transparent; } +/* Destructive items of a table row action menu (x-table.row-actions). */ +.row-actions-danger .listbox-option, +.dark .row-actions-danger .listbox-option { + color: var(--color-error); +} + /* Searchable listbox: sticky search field + scrollable options */ .searchable-listbox-panel { max-height: 18rem; @@ -3150,7 +3156,7 @@ input[type="search"]::-webkit-search-results-decoration { } .env-table-grid { - grid-template-columns: minmax(14rem, 2.5fr) 4.8rem 6rem 4rem 4.5rem 4.8rem 4.2rem 3rem; + grid-template-columns: minmax(14rem, 2.5fr) 4.8rem 6rem 4rem 4.5rem 4.8rem 4.2rem 4.5rem; } /* File browser: icon, name, perms, size, modified, actions. @@ -3198,11 +3204,11 @@ input[type="search"]::-webkit-search-results-decoration { } .environment-table-scroll .env-table-grid { - min-width: 53rem; + min-width: 54.5rem; } .env-table-grid.env-table-grid-no-type { - grid-template-columns: minmax(14rem, 2.5fr) 4.8rem 4rem 4.5rem 4.8rem 4.2rem 3rem; + grid-template-columns: minmax(14rem, 2.5fr) 4.8rem 4rem 4.5rem 4.8rem 4.2rem 4.5rem; } @media (max-width: 768px) { @@ -3225,20 +3231,20 @@ input[type="search"]::-webkit-search-results-decoration { } .data-table-row.env-table-grid > :last-child { - display: block; + display: flex; justify-self: end; } } /* Shared variables only store value shape (multiline), not per-resource flags. */ .env-table-grid-shared { - grid-template-columns: minmax(0, 1.6fr) 6rem minmax(0, 1fr) 4.5rem 3rem; + grid-template-columns: minmax(0, 1.6fr) 6rem minmax(0, 1fr) 4.5rem 4.5rem; } /* Shared env vars collapse secondary columns on tablet and use cards on phone. */ @media (max-width: 1100px) { .env-table-grid-shared { - grid-template-columns: minmax(0, 1.4fr) 6rem minmax(0, 1fr) 3rem; + grid-template-columns: minmax(0, 1.4fr) 6rem minmax(0, 1fr) 4.5rem; gap: 0.75rem; } @@ -3250,7 +3256,7 @@ input[type="search"]::-webkit-search-results-decoration { @media (max-width: 900px) { .env-table-grid-shared { - grid-template-columns: minmax(0, 1fr) 6rem 3rem; + grid-template-columns: minmax(0, 1fr) 6rem 4.5rem; } .env-table-grid-shared > :nth-child(3) { @@ -3505,7 +3511,7 @@ input[type="search"]::-webkit-search-results-decoration { } .service-backup-table-grid { - grid-template-columns: minmax(10rem, 1.7fr) 6rem minmax(7rem, 0.8fr) 7.5rem 6.5rem minmax(8rem, 1fr) 12.5rem; + grid-template-columns: minmax(10rem, 1.7fr) 6rem minmax(7rem, 0.8fr) 7.5rem 6.5rem minmax(8rem, 1fr) 4.5rem; width: 100%; } @@ -3533,11 +3539,11 @@ input[type="search"]::-webkit-search-results-decoration { } .volumes-table-grid { - grid-template-columns: minmax(9rem, 1.2fr) minmax(6rem, 1fr) 5rem 15rem; + grid-template-columns: minmax(9rem, 1.2fr) minmax(6rem, 1fr) 5rem 4.5rem; } .volumes-table-grid-with-pr { - grid-template-columns: minmax(9rem, 1.1fr) minmax(6rem, 1fr) 8.5rem 5rem 15rem; + grid-template-columns: minmax(9rem, 1.1fr) minmax(6rem, 1fr) 8.5rem 5rem 4.5rem; } .volumes-table-grid-readonly.has-source { @@ -3545,11 +3551,11 @@ input[type="search"]::-webkit-search-results-decoration { } .volumes-table-grid.has-source { - grid-template-columns: minmax(9rem, 1.1fr) minmax(14rem, 1.5fr) minmax(6rem, 1fr) 5rem 15rem; + grid-template-columns: minmax(9rem, 1.1fr) minmax(14rem, 1.5fr) minmax(6rem, 1fr) 5rem 4.5rem; } .volumes-table-grid-with-pr.has-source { - grid-template-columns: minmax(9rem, 1fr) minmax(14rem, 1.4fr) minmax(6rem, 1fr) 8.5rem 5rem 15rem; + grid-template-columns: minmax(9rem, 1fr) minmax(14rem, 1.4fr) minmax(6rem, 1fr) 8.5rem 5rem 4.5rem; } .volumes-mobile-label { @@ -3795,7 +3801,7 @@ input[type="search"]::-webkit-search-results-decoration { } .server-resources-unmanaged-table-grid { - grid-template-columns: minmax(9rem, 1fr) minmax(12rem, 1.5fr) 7rem minmax(9rem, auto); + grid-template-columns: minmax(9rem, 1fr) minmax(12rem, 1.5fr) 7rem 4.5rem; } .server-images-table-grid { @@ -6821,13 +6827,14 @@ html.dark .resource-glyph { color: var(--color-brand-light); } +/* Row and card actions stay neutral: the brand color is for the primary action of an area. */ html.dark .card-icon-button { - color: var(--color-brand-light); + color: var(--color-fg-faint); } html.dark .card-icon-button:hover { - background-color: color-mix(in srgb, var(--color-brand) 16%, transparent); - color: #fff; + background-color: rgb(255 255 255 / 0.06); + color: var(--color-fg); } html.dark .app-main :is(article.group, a.group).rounded-xl { diff --git a/resources/views/components/shared-variables/editor.blade.php b/resources/views/components/shared-variables/editor.blade.php index 18ed216172..2d33ef22cb 100644 --- a/resources/views/components/shared-variables/editor.blade.php +++ b/resources/views/components/shared-variables/editor.blade.php @@ -116,7 +116,7 @@ Scope {{ count($readOnlyKeys) ? 'Value / comment' : 'Comment' }} Multiline - + Actions @foreach ($variables as $env) @if (in_array($env->key, $readOnlyKeys)) diff --git a/resources/views/components/table/row-action.blade.php b/resources/views/components/table/row-action.blade.php new file mode 100644 index 0000000000..3996e27665 --- /dev/null +++ b/resources/views/components/table/row-action.blade.php @@ -0,0 +1,10 @@ +{{-- One item of . Renders a link (with wire:navigate when enabled) when href is set. --}} +@props([ + 'href' => null, +]) + +@if ($href) + class('listbox-option justify-start!') }}>{{ $slot }} +@else + +@endif diff --git a/resources/views/components/table/row-actions.blade.php b/resources/views/components/table/row-actions.blade.php new file mode 100644 index 0000000000..9b2599e9a3 --- /dev/null +++ b/resources/views/components/table/row-actions.blade.php @@ -0,0 +1,27 @@ +{{-- Row action menu for tables: a "..." icon button at the far right of the row. + Put items in the default slot. Put destructive items in + the danger slot: they show in red, below a divider. A click on any item + closes the menu, also when the item opens a modal. --}} +@props([ + 'label' => 'Actions', +]) + + + + + +
+ {{ $slot }} + @if (isset($danger) && $danger->isNotEmpty()) + @if ($slot->isNotEmpty()) +
+ @endif +
+ {{ $danger }} +
+ @endif +
+
diff --git a/resources/views/livewire/admin/index.blade.php b/resources/views/livewire/admin/index.blade.php index c2fb4b271e..5320f2de50 100644 --- a/resources/views/livewire/admin/index.blade.php +++ b/resources/views/livewire/admin/index.blade.php @@ -64,7 +64,7 @@ Name Email Subscription - Action + Actions @foreach ($foundUsers as $user) @php diff --git a/resources/views/livewire/dashboard.blade.php b/resources/views/livewire/dashboard.blade.php index d551fd7d4b..dbcebc8bab 100644 --- a/resources/views/livewire/dashboard.blade.php +++ b/resources/views/livewire/dashboard.blade.php @@ -162,7 +162,7 @@
-
+
-
+ Actions
@foreach ($dashboardProjects as $project) @php $firstEnvironment = $project->environments->first(); @endphp
+ class="relative grid grid-cols-[minmax(0,1fr)_7rem_4.5rem] gap-4 @2xl:min-w-[560px] @2xl:grid-cols-[minmax(0,1.2fr)_7rem_minmax(0,1.5fr)_4.5rem] {{ $tableRow }}">
diff --git a/resources/views/livewire/project/application/partials/domain-row.blade.php b/resources/views/livewire/project/application/partials/domain-row.blade.php index 23d2bf1f0a..874914428d 100644 --- a/resources/views/livewire/project/application/partials/domain-row.blade.php +++ b/resources/views/livewire/project/application/partials/domain-row.blade.php @@ -131,14 +131,14 @@
@can('update', $application) - - @unless ($labelsAreWritable) - @if ($isSuggested) + @if ($labelsAreWritable || $isSuggested) + + @if ($isSuggested && ! $labelsAreWritable) @if ($row['needs_force_add'] ?? false) Continue @@ -148,29 +148,34 @@ Add domain @endif - @else - - - - - - @endif - @endunless + @else + + + Check DNS + + + Edit + + + + + Delete + + + + + @endif @endcan
diff --git a/resources/views/livewire/project/application/preview-domains.blade.php b/resources/views/livewire/project/application/preview-domains.blade.php index c84480eb9a..f21096b91d 100644 --- a/resources/views/livewire/project/application/preview-domains.blade.php +++ b/resources/views/livewire/project/application/preview-domains.blade.php @@ -177,34 +177,33 @@
@can('update', $preview->application) - - - - - - - + + + Check DNS + + + Edit + + + + + Delete + + + + @endcan
diff --git a/resources/views/livewire/project/database/scheduled-backups.blade.php b/resources/views/livewire/project/database/scheduled-backups.blade.php index aba61ec48c..67c8f441df 100644 --- a/resources/views/livewire/project/database/scheduled-backups.blade.php +++ b/resources/views/livewire/project/database/scheduled-backups.blade.php @@ -62,7 +62,7 @@ Latest run S3 storage Executions - Action + Actions @foreach ($database->scheduledBackups as $backup) @php @@ -87,9 +87,10 @@ || @js(strtolower($s3StorageNames)).includes(search.toLowerCase())" class="data-table-row scheduled-backups-table-grid border-b border-neutral-200 last:border-b-0 dark:border-white/[0.06]">
@@ -107,7 +108,10 @@
@endforeach diff --git a/resources/views/livewire/project/index.blade.php b/resources/views/livewire/project/index.blade.php index de563683a8..75e060fd9f 100644 --- a/resources/views/livewire/project/index.blade.php +++ b/resources/views/livewire/project/index.blade.php @@ -149,7 +149,7 @@ -
+ Actions