Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 70 additions & 1 deletion dist/filament-lms.css
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@

/* Centralized step material sizing */
.step-material-container {
width: 100%;
height: 60vh;
max-width: calc(60vh * 16/9);
max-width: min(100%, calc(60vh * 16 / 9));
margin: 0 auto;
}

Expand Down Expand Up @@ -175,3 +176,71 @@ body.lms-embedded-player .fi-main {
font-size: 0.9375rem;
line-height: 1.45;
}

[x-cloak] {
display: none !important;
}

.lms-image-preview__trigger {
display: block;
width: 100%;
padding: 0;
border: 0;
background: transparent;
cursor: zoom-in;
text-align: inherit;
}

.lms-image-preview__hint {
display: block;
margin-top: 0.5rem;
font-size: 0.875rem;
color: rgb(107 114 128);
text-align: center;
}

.lms-image-lightbox {
position: fixed;
inset: 0;
z-index: 80;
background: rgb(15 23 42 / 0.92);
}

.lms-image-lightbox__close {
position: fixed;
top: 1rem;
right: 1rem;
z-index: 81;
padding: 0.5rem 0.875rem;
border: 0;
border-radius: 0.5rem;
background: rgb(255 255 255);
color: rgb(15 23 42);
font-size: 0.875rem;
font-weight: 600;
cursor: pointer;
}

.lms-image-lightbox__scroller {
width: 100%;
height: 100%;
overflow: auto;
touch-action: pan-x pan-y pinch-zoom;
-webkit-overflow-scrolling: touch;
}

.lms-image-lightbox__scroller img {
display: block;
width: auto;
height: auto;
max-width: none;
margin: 2.5rem auto;
}

body.lms-image-lightbox-open {
overflow: hidden;
}

body.lms-image-lightbox-open .next-button {
visibility: hidden;
}
71 changes: 70 additions & 1 deletion resources/css/plugin.css
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@

/* Centralized step material sizing */
.step-material-container {
width: 100%;
height: 60vh;
max-width: calc(60vh * 16/9);
max-width: min(100%, calc(60vh * 16 / 9));
margin: 0 auto;
}

Expand Down Expand Up @@ -175,3 +176,71 @@ body.lms-embedded-player .fi-main {
font-size: 0.9375rem;
line-height: 1.45;
}

[x-cloak] {
display: none !important;
}

.lms-image-preview__trigger {
display: block;
width: 100%;
padding: 0;
border: 0;
background: transparent;
cursor: zoom-in;
text-align: inherit;
}

.lms-image-preview__hint {
display: block;
margin-top: 0.5rem;
font-size: 0.875rem;
color: rgb(107 114 128);
text-align: center;
}

.lms-image-lightbox {
position: fixed;
inset: 0;
z-index: 80;
background: rgb(15 23 42 / 0.92);
}

.lms-image-lightbox__close {
position: fixed;
top: 1rem;
right: 1rem;
z-index: 81;
padding: 0.5rem 0.875rem;
border: 0;
border-radius: 0.5rem;
background: rgb(255 255 255);
color: rgb(15 23 42);
font-size: 0.875rem;
font-weight: 600;
cursor: pointer;
}

.lms-image-lightbox__scroller {
width: 100%;
height: 100%;
overflow: auto;
touch-action: pan-x pan-y pinch-zoom;
-webkit-overflow-scrolling: touch;
}

.lms-image-lightbox__scroller img {
display: block;
width: auto;
height: auto;
max-width: none;
margin: 2.5rem auto;
}

body.lms-image-lightbox-open {
overflow: hidden;
}

body.lms-image-lightbox-open .next-button {
visibility: hidden;
}
14 changes: 8 additions & 6 deletions resources/views/livewire/document-step.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@ class="flex-1 flex flex-col"
>
<div class="mb-8 flex-1">
@if($this->getPreviewImage())
<img
src="{{ $this->getPreviewImage() }}"
alt="Document Preview Image"
class="step-material-container rounded-lg border border-gray-300 cursor-pointer"
wire:click="download"
/>
<div class="step-material-container">
<img
src="{{ $this->getPreviewImage() }}"
alt="Document Preview Image"
class="rounded-lg border border-gray-300 cursor-pointer"
wire:click="download"
/>
</div>
@elseif ($document->hasScormPackage())
<div class="step-material-container step-material-container--interactive w-full">
<iframe
Expand Down
55 changes: 49 additions & 6 deletions resources/views/livewire/image-step.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,57 @@ class="flex-1 flex flex-col"
>
<div class="mb-8 flex-1">
@if($this->getImageUrl())
<img
src="{{ $this->getImageUrl() }}"
class="step-material-container rounded-lg border border-gray-300"
alt="Step Image"
/>
<div
class="lms-image-preview"
x-data="{ open: false }"
x-effect="document.body.classList.toggle('lms-image-lightbox-open', open)"
@keydown.escape.window="open = false"
>
<button
type="button"
class="lms-image-preview__trigger"
@click="open = true; $nextTick(() => $refs.closeBtn?.focus())"
aria-label="View larger image"
>
<div class="step-material-container">
<img
src="{{ $this->getImageUrl() }}"
class="rounded-lg border border-gray-300"
alt="Step Image"
/>
</div>
<span class="lms-image-preview__hint">Tap to zoom</span>
</button>

<div
x-show="open"
x-cloak
class="lms-image-lightbox"
role="dialog"
aria-modal="true"
aria-label="Image preview"
@click.self="open = false"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Backdrop click cannot close lightbox

Medium Severity

@click.self on .lms-image-lightbox never runs because .lms-image-lightbox__scroller is sized to 100% width and height and sits on top of the dialog, so taps hit the scroller instead of the lightbox. Close and Escape still work, but the advertised backdrop dismiss does not.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 43df6cd. Configure here.

>
<button
type="button"
class="lms-image-lightbox__close"
x-ref="closeBtn"
@click="open = false"
aria-label="Close image preview"
>
Close
</button>
<div class="lms-image-lightbox__scroller">
<img
src="{{ $this->getImageUrl() }}"
alt="Step Image"
/>
</div>
</div>
</div>
@endif
</div>
</x-filament::section>

<x-filament-lms::next-button />
</div>
</div>
72 changes: 72 additions & 0 deletions tests/Feature/ImageStepTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<?php

namespace Tapp\FilamentLms\Tests\Feature;

use Illuminate\Contracts\Support\MessageBag as MessageBagContract;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\MessageBag;
use Livewire\Livewire;
use Tapp\FilamentLms\Livewire\ImageStep;
use Tapp\FilamentLms\Models\Course;
use Tapp\FilamentLms\Models\Image;
use Tapp\FilamentLms\Models\Lesson;
use Tapp\FilamentLms\Models\Step;
use Tapp\FilamentLms\Tests\TestUser;

class ImageStepWithErrorBag extends ImageStep
{
public function getErrorBag(): MessageBagContract
{
return new MessageBag;
}
}

beforeEach(function () {
if (! Schema::hasColumn('lms_images', 'deleted_at')) {
Schema::table('lms_images', function (Blueprint $table) {
$table->softDeletes();
});
}
});

test('image step wraps the image in the material container', function () {
$user = TestUser::create([
'name' => 'Test User',
'email' => 'image-step@example.com',
'password' => bcrypt('password'),
]);

$this->actingAs($user);

$course = Course::factory()->create();
$lesson = Lesson::factory()->create(['course_id' => $course->id]);

$image = Image::query()->create([
'name' => 'Landscape',
'file_path' => 'images/landscape.png',
]);

$path = sys_get_temp_dir().'/lms-landscape-test.png';
$png = imagecreatetruecolor(16, 9);
imagepng($png, $path);

$image->addMedia($path)->preservingOriginal()->toMediaCollection('image');

$step = Step::factory()->create([
'lesson_id' => $lesson->id,
'name' => 'Landscape Image',
'slug' => 'landscape-image',
'material_type' => 'image',
'material_id' => $image->id,
]);

$html = Livewire::test(ImageStepWithErrorBag::class, ['step' => $step->fresh(['material'])])->html();

expect($html)
->toContain('class="step-material-container"')
->toContain('<img')
->toContain('role="dialog"')
->toContain('Tap to zoom')
->not->toContain('class="step-material-container rounded-lg');
});
Loading