F
Filament11mo ago
bionary

Anybody find a decent solution for table images to a lightbox?

(I'm surprised filament doesn't have a builtin lightbox for table records...it seems to have everything else imaginable!) The 2 lightbox plugins are not solutions. - https://filamentphp.com/plugins/njxqlus-lightbox This plugin doesn't support use in tables, so that's of no help here. - https://filamentphp.com/plugins/solution-forest-simplelightbox This plugin simply doesn't work and doesn't seem to be actively maintained.
15 Replies
_andypeacock
_andypeacock7mo ago
Hi @bionary I found the same problem as you. Did you find a solution? Actually, thanks to Cursor, I've already got a solution:
Tables\Columns\TextColumn::make('name')
->searchable()
->action(
Action::make('viewThumbnail')
->label('View Thumbnail')
->icon('heroicon-o-photograph')
->modalHeading(fn ($record) => "Thumbnail for {$record->name}")
->modalContent(fn ($record) => view('filament.tables.thumbnail-modal', [ 'imageUrl' => $record->thumbnail_url ]))
->modalSubmitAction(false)
->modalCancelAction(false)
),
Tables\Columns\TextColumn::make('name')
->searchable()
->action(
Action::make('viewThumbnail')
->label('View Thumbnail')
->icon('heroicon-o-photograph')
->modalHeading(fn ($record) => "Thumbnail for {$record->name}")
->modalContent(fn ($record) => view('filament.tables.thumbnail-modal', [ 'imageUrl' => $record->thumbnail_url ]))
->modalSubmitAction(false)
->modalCancelAction(false)
),
Then the filament.tables.thumbnail_modal.blade.php:
<div class="flex justify-center">
<img src="{{ $imageUrl }}" alt="Block Thumbnail" class="max-w-full max-h-[80vh]">
</div>
<div class="flex justify-center">
<img src="{{ $imageUrl }}" alt="Block Thumbnail" class="max-w-full max-h-[80vh]">
</div>
awcodes
awcodes7mo ago
Just create a custom column whose action opens a modal with a custom view which is just an img tag with the src for the image.
_andypeacock
_andypeacock7mo ago
Thanks Adam - Just replied with the same.
awcodes
awcodes7mo ago
Don’t even need an additional script
_andypeacock
_andypeacock7mo ago
Obvious, now I see the solution
awcodes
awcodes7mo ago
😇
bionary
bionaryOP7mo ago
@_andypeacock Your solution looks a lot smarter/cleaner than what I came up with. Thank you. I was doing something similar but packing it all in the Filament Resource like this:
SpatieMediaLibraryImageColumn::make($dotNotationMediaPath)
->action(
Actions\Action::make($dotNotationMediaPath)
->modalHeading(false)
->extraModalWindowAttributes(['class'=>'justify-center h-[calc(100vh-100px)]', 'style'=>'flex-direction:inherit'])
->modalContent(function($record){
$imageUrl = $record?->getFirstMedia($collection)?->getUrl('preview');
return new HtmlString("<img src='$imageUrl' class='object-scale-down max-h-full p-4'>");
})
->modalFooterActions(fn() => [])
SpatieMediaLibraryImageColumn::make($dotNotationMediaPath)
->action(
Actions\Action::make($dotNotationMediaPath)
->modalHeading(false)
->extraModalWindowAttributes(['class'=>'justify-center h-[calc(100vh-100px)]', 'style'=>'flex-direction:inherit'])
->modalContent(function($record){
$imageUrl = $record?->getFirstMedia($collection)?->getUrl('preview');
return new HtmlString("<img src='$imageUrl' class='object-scale-down max-h-full p-4'>");
})
->modalFooterActions(fn() => [])
I never quite found a way to scale the image properly. Even with my custom class added to the image, it was still not scaling properly and would get cut off if the aspect ratio was extreme. Also the white border around the image was never equal/balanced...but my tailwind skills are junk. Can't wait to try your solution, thanks!
_andypeacock
_andypeacock7mo ago
Hi, don't thank me, thank cursor😀 Also, mine doesn't scale either, I realised later. I've parked it for now, as it wasn't critical for me.
SimonH
SimonH2d ago
Just came across this as i am also trying to implement a lightbox in tables and infolists, i used the solution that @_andypeacock posted and it worked well on the infolist, but is very slow on tables. Looking at the network tab it seems like it is reloading all images for the entire table, below is my action code, what can i do to only load the clicked on image?
Tables\Columns\ImageColumn::make('artboard_url')
->label('Artboard')
->action(
Action::make('viewThumbnail')
->icon('heroicon-o-photograph')
->modalHeading(fn ($record) => "Artboard: {$record->title}")
->modalContent(fn ($record) => view('filament.modals.lightbox', [ 'imageUrl' => $record->artboard_url ]))
->modalSubmitAction(false)
->modalCancelAction(false)
),
Tables\Columns\ImageColumn::make('artboard_url')
->label('Artboard')
->action(
Action::make('viewThumbnail')
->icon('heroicon-o-photograph')
->modalHeading(fn ($record) => "Artboard: {$record->title}")
->modalContent(fn ($record) => view('filament.modals.lightbox', [ 'imageUrl' => $record->artboard_url ]))
->modalSubmitAction(false)
->modalCancelAction(false)
),
_andypeacock
_andypeacock2d ago
I'm on from mobile at the moment, but my sight loads the modal very quickly. I don't remember having any issues, but let me check and I'll come back in case I made any last minute changes. Ah, I did. Now have
ImageColumn::make('thumbnail_url')
->label('Thumbnail')
->toggleable()
->width(300)
->height('100%')
->extraAttributes(fn ($record) => [
'class' => 'cursor-pointer',
'x-on:click' => '$store.lightbox.openLightbox($el.getAttribute("data-thumbnail-url"))',
'data-thumbnail-url' => $record->thumbnail_url,
]),
ImageColumn::make('thumbnail_url')
->label('Thumbnail')
->toggleable()
->width(300)
->height('100%')
->extraAttributes(fn ($record) => [
'class' => 'cursor-pointer',
'x-on:click' => '$store.lightbox.openLightbox($el.getAttribute("data-thumbnail-url"))',
'data-thumbnail-url' => $record->thumbnail_url,
]),
Ah, theres a blade file and render hook. Let me get back to my laptop (about 3-4 hours from now) and I'll pull it all together.
SimonH
SimonH2d ago
thanks, I really appreciate your help
SimonH
SimonH2d ago
Once again @Povilas K with the detailed performance breakdown. Looks like i am running into a known issue with modals on large livewire tables. In this case, the image URL is already available on the frontend so it should not require a roundtrip to the server to render the modal, it could be done with JS on the FE, looks like that is what you ultimately went with @_andypeacock
Filament Daily
YouTube
Slow Modals in Filament: Livewire Performance Issue
Let's talk about a slow behavior of modals on more complex pages of Filament. And the reasons. Links mentioned in the video: - Original tweet: https://x.com/joseph_ajibodu/status/1809187763142775088 - Video "Filament PHP performance Issue" https://www.youtube.com/watch?v=ZDW8NBzVdpo and a follow-up "Solution to Filament PHP Performance issue" h...
_andypeacock
_andypeacock2d ago
Hi @SimonH At the laptop at last. So, three parts 1. the filament column above 2. In your main provider:
FilamentView::registerRenderHook(
PanelsRenderHook::BODY_END,
fn (): \Illuminate\Contracts\View\View => view('filament.tables.lightbox'),
scopes: [
YourFilamentResource::class,
],
);
FilamentView::registerRenderHook(
PanelsRenderHook::BODY_END,
fn (): \Illuminate\Contracts\View\View => view('filament.tables.lightbox'),
scopes: [
YourFilamentResource::class,
],
);
3. the lightbox blade template Hope that helps! <div x-data x-cloak> <div x-show="$store.lightbox.show" x-on:keydown.escape.window="$store.lightbox.show = false" class="fixed inset-0 z-50 flex items-center justify-center bg-black bg-opacity-50" x-transition:enter="transition ease-out duration-300" x-transition:enter-start="opacity-0" x-transition:enter-end="opacity-100" x-transition:leave="transition ease-in duration-300" x-transition:leave-start="opacity-100" x-transition:leave-end="opacity-0"> <div class="relative max-w-3xl max-h-full bg-gray-100 p-12 rounded-lg shadow-xl" x-on:click.outside="$store.lightbox.show = false"> <img :src="$store.lightbox.imageUrl" alt="Lightbox image" class="max-h-[80vh] max-w-full rounded border border-gray-300"> <button @click="$store.lightbox.show = false" class="absolute top-3 right-3 p-2 bg-white border border-gray-300 rounded-md hover:bg-gray-50 hover:border-gray-400 transition-all duration-200"> <svg class="w-4 h-4 text-gray-600" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"> </path> </svg> </button> </div> </div> </div> <script> document.addEventListener('alpine:init', () => { Alpine.store('lightbox', { show: false, imageUrl: null, openLightbox(url) { this.imageUrl = url; this.show = true; }, closeLightbox() { this.show = false; this.imageUrl = null; }, }); }); </script>
_andypeacock
_andypeacock2d ago
It's snappy: https://somup.com/cTfuYzsRgF (the first pause isn't the modal - it's me giving you a moment to absorb what you're looking at)
ScreenPal (Formerly Screencast-O-Matic)
Lightbox in filament
SimonH
SimonH2d ago
thanks I want to use this on multiple panels so i created a middleware for it, seems to be orking but now on click it shows the modal but then immediatley directs to teh record view page. Did you disable the row click for the entire table or did you find a way to disable it just for this column? I thought that ->url(null) would work, but it is not enought to override default behaviour. ->url("#") did however work working nice and snappy now thanks @_andypeacock Now i got to learn more about tailwind and asset management in filament to get it sized just right

Did you find this page helpful?