|
200 | 200 |
|
201 | 201 | <div |
202 | 202 | class={[ |
203 | | - 'focus-visible:outline-none flex overflow-hidden', |
| 203 | + 'group focus-visible:outline-none focus-visible:rounded-lg flex overflow-hidden', |
204 | 204 | disabled ? 'bg-gray-300' : 'dark:bg-neutral-700 bg-neutral-200', |
| 205 | + { 'rounded-xl': selected }, |
205 | 206 | ]} |
206 | 207 | style:width="{width}px" |
207 | 208 | style:height="{height}px" |
|
223 | 224 | bind:this={element} |
224 | 225 | data-asset={asset.id} |
225 | 226 | data-thumbnail-focus-container |
| 227 | + data-selected={selected ? true : undefined} |
226 | 228 | tabindex={0} |
227 | 229 | role="link" |
228 | 230 | > |
229 | | - <!-- Outline on focus --> |
230 | | - <div |
231 | | - class={[ |
232 | | - 'pointer-events-none absolute z-1 size-full outline-hidden outline-4 -outline-offset-4 outline-immich-primary', |
233 | | - { 'rounded-xl': selected }, |
234 | | - ]} |
235 | | - data-outline |
236 | | - ></div> |
237 | | - |
238 | 231 | <div |
239 | 232 | class={['group absolute top-0 bottom-0', { 'cursor-not-allowed': disabled, 'cursor-pointer': !disabled }]} |
240 | 233 | style:width="inherit" |
|
247 | 240 | { 'rounded-xl': selected }, |
248 | 241 | ]} |
249 | 242 | > |
| 243 | + <ImageThumbnail |
| 244 | + class={['absolute group-focus-visible:rounded-lg', { 'rounded-xl': selected }, imageClass]} |
| 245 | + brokenAssetClass={['z-1 absolute group-focus-visible:rounded-lg', { 'rounded-xl': selected }, brokenAssetClass]} |
| 246 | + url={getAssetMediaUrl({ id: asset.id, size: AssetMediaSize.Thumbnail, cacheKey: asset.thumbhash })} |
| 247 | + altText={$getAltText(asset)} |
| 248 | + widthStyle="{width}px" |
| 249 | + heightStyle="{height}px" |
| 250 | + curve={selected} |
| 251 | + onComplete={(errored) => ((loaded = true), (thumbError = errored))} |
| 252 | + /> |
| 253 | + {#if asset.isVideo} |
| 254 | + <div class="absolute h-full w-full pointer-events-none group-focus-visible:rounded-lg"> |
| 255 | + <VideoThumbnail |
| 256 | + class="group-focus-visible:rounded-lg" |
| 257 | + url={getAssetPlaybackUrl({ id: asset.id, cacheKey: asset.thumbhash })} |
| 258 | + enablePlayback={mouseOver && $playVideoThumbnailOnHover} |
| 259 | + curve={selected} |
| 260 | + durationInSeconds={asset.duration ? timeToSeconds(asset.duration) : 0} |
| 261 | + playbackOnIconHover={!$playVideoThumbnailOnHover} |
| 262 | + /> |
| 263 | + </div> |
| 264 | + {:else if asset.isImage && asset.livePhotoVideoId} |
| 265 | + <div class="absolute h-full w-full pointer-events-none group-focus-visible:rounded-lg"> |
| 266 | + <VideoThumbnail |
| 267 | + class="group-focus-visible:rounded-lg" |
| 268 | + url={getAssetPlaybackUrl({ id: asset.livePhotoVideoId, cacheKey: asset.thumbhash })} |
| 269 | + enablePlayback={mouseOver && $playVideoThumbnailOnHover} |
| 270 | + pauseIcon={mdiMotionPauseOutline} |
| 271 | + playIcon={mdiMotionPlayOutline} |
| 272 | + showTime={false} |
| 273 | + curve={selected} |
| 274 | + playbackOnIconHover={!$playVideoThumbnailOnHover} |
| 275 | + /> |
| 276 | + </div> |
| 277 | + {:else if asset.isImage && asset.duration && !asset.duration.includes('0:00:00.000') && mouseOver} |
| 278 | + <!-- GIF --> |
| 279 | + <div class="absolute top-0 h-full w-full pointer-events-none"> |
| 280 | + <div class="absolute h-full w-full bg-linear-to-b from-black/25 via-[transparent_25%]"></div> |
| 281 | + <ImageThumbnail |
| 282 | + class={imageClass} |
| 283 | + {brokenAssetClass} |
| 284 | + url={getAssetMediaUrl({ id: asset.id, size: AssetMediaSize.Original, cacheKey: asset.thumbhash })} |
| 285 | + altText={$getAltText(asset)} |
| 286 | + widthStyle="{width}px" |
| 287 | + heightStyle="{height}px" |
| 288 | + curve={selected} |
| 289 | + /> |
| 290 | + <div class="absolute end-0 top-0 flex place-items-center gap-1 text-xs font-medium text-white"> |
| 291 | + <span class="pe-2 pt-2"> |
| 292 | + <Icon data-icon-playable-pause icon={mdiMotionPauseOutline} size="24" /> |
| 293 | + </span> |
| 294 | + </div> |
| 295 | + </div> |
| 296 | + {/if} |
| 297 | + |
| 298 | + {#if (!loaded || thumbError) && asset.thumbhash} |
| 299 | + <canvas |
| 300 | + use:thumbhash={{ base64ThumbHash: asset.thumbhash }} |
| 301 | + data-testid="thumbhash" |
| 302 | + class="absolute top-0 object-cover group-focus-visible:rounded-lg" |
| 303 | + style:width="{width}px" |
| 304 | + style:height="{height}px" |
| 305 | + class:rounded-xl={selected} |
| 306 | + draggable="false" |
| 307 | + out:fade={{ duration: THUMBHASH_FADE_DURATION }} |
| 308 | + ></canvas> |
| 309 | + {/if} |
| 310 | + |
250 | 311 | <!-- icon overlay --> |
251 | 312 | <div> |
252 | 313 | <!-- Gradient overlay on hover --> |
253 | 314 | {#if !usingMobileDevice && !disabled} |
254 | 315 | <div |
255 | 316 | class={[ |
256 | | - 'absolute h-full w-full bg-linear-to-b from-black/25 via-[transparent_25%] opacity-0 transition-opacity group-hover:opacity-100', |
| 317 | + 'absolute h-full w-full bg-linear-to-b from-black/25 via-[transparent_25%] opacity-0 transition-opacity group-hover:opacity-100 group-focus-visible:rounded-lg', |
257 | 318 | { 'rounded-xl': selected }, |
258 | 319 | ]} |
259 | 320 | ></div> |
260 | 321 | {/if} |
261 | 322 |
|
262 | 323 | <!-- Dimmed support --> |
263 | 324 | {#if dimmed && !mouseOver} |
264 | | - <div id="a" class={['absolute h-full w-full bg-gray-700/40', { 'rounded-xl': selected }]}></div> |
| 325 | + <div |
| 326 | + id="a" |
| 327 | + class={['absolute h-full w-full bg-gray-700/40 group-focus-visible:rounded-lg', { 'rounded-xl': selected }]} |
| 328 | + ></div> |
265 | 329 | {/if} |
266 | 330 |
|
267 | 331 | <!-- Favorite asset star --> |
|
329 | 393 | > |
330 | 394 | </a> |
331 | 395 | {/if} |
332 | | - |
333 | | - <ImageThumbnail |
334 | | - class={imageClass} |
335 | | - {brokenAssetClass} |
336 | | - url={getAssetMediaUrl({ id: asset.id, size: AssetMediaSize.Thumbnail, cacheKey: asset.thumbhash })} |
337 | | - altText={$getAltText(asset)} |
338 | | - widthStyle="{width}px" |
339 | | - heightStyle="{height}px" |
340 | | - curve={selected} |
341 | | - onComplete={(errored) => ((loaded = true), (thumbError = errored))} |
342 | | - /> |
343 | | - {#if asset.isVideo} |
344 | | - <div class="absolute top-0 h-full w-full pointer-events-none"> |
345 | | - <VideoThumbnail |
346 | | - url={getAssetPlaybackUrl({ id: asset.id, cacheKey: asset.thumbhash })} |
347 | | - enablePlayback={mouseOver && $playVideoThumbnailOnHover} |
348 | | - curve={selected} |
349 | | - durationInSeconds={asset.duration ? timeToSeconds(asset.duration) : 0} |
350 | | - playbackOnIconHover={!$playVideoThumbnailOnHover} |
351 | | - /> |
352 | | - </div> |
353 | | - {:else if asset.isImage && asset.livePhotoVideoId} |
354 | | - <div class="absolute top-0 h-full w-full pointer-events-none"> |
355 | | - <VideoThumbnail |
356 | | - url={getAssetPlaybackUrl({ id: asset.livePhotoVideoId, cacheKey: asset.thumbhash })} |
357 | | - enablePlayback={mouseOver && $playVideoThumbnailOnHover} |
358 | | - pauseIcon={mdiMotionPauseOutline} |
359 | | - playIcon={mdiMotionPlayOutline} |
360 | | - showTime={false} |
361 | | - curve={selected} |
362 | | - playbackOnIconHover={!$playVideoThumbnailOnHover} |
363 | | - /> |
364 | | - </div> |
365 | | - {:else if asset.isImage && asset.duration && !asset.duration.includes('0:00:00.000') && mouseOver} |
366 | | - <!-- GIF --> |
367 | | - <div class="absolute top-0 h-full w-full pointer-events-none"> |
368 | | - <div class="absolute h-full w-full bg-linear-to-b from-black/25 via-[transparent_25%]"></div> |
369 | | - <ImageThumbnail |
370 | | - class={imageClass} |
371 | | - {brokenAssetClass} |
372 | | - url={getAssetMediaUrl({ id: asset.id, size: AssetMediaSize.Original, cacheKey: asset.thumbhash })} |
373 | | - altText={$getAltText(asset)} |
374 | | - widthStyle="{width}px" |
375 | | - heightStyle="{height}px" |
376 | | - curve={selected} |
377 | | - /> |
378 | | - <div class="absolute end-0 top-0 flex place-items-center gap-1 text-xs font-medium text-white"> |
379 | | - <span class="pe-2 pt-2"> |
380 | | - <Icon data-icon-playable-pause icon={mdiMotionPauseOutline} size="24" /> |
381 | | - </span> |
382 | | - </div> |
383 | | - </div> |
384 | | - {/if} |
385 | | - |
386 | | - {#if (!loaded || thumbError) && asset.thumbhash} |
387 | | - <canvas |
388 | | - use:thumbhash={{ base64ThumbHash: asset.thumbhash }} |
389 | | - data-testid="thumbhash" |
390 | | - class="absolute top-0 object-cover" |
391 | | - style:width="{width}px" |
392 | | - style:height="{height}px" |
393 | | - class:rounded-xl={selected} |
394 | | - draggable="false" |
395 | | - out:fade={{ duration: THUMBHASH_FADE_DURATION }} |
396 | | - ></canvas> |
397 | | - {/if} |
398 | 396 | </div> |
399 | 397 |
|
400 | 398 | {#if selectionCandidate} |
|
427 | 425 | {/if} |
428 | 426 | </button> |
429 | 427 | {/if} |
| 428 | + |
| 429 | + <!-- Outline on focus --> |
| 430 | + <div |
| 431 | + class={[ |
| 432 | + 'pointer-events-none absolute z-1 size-full outline-immich-primary dark:outline-immich-dark-primary group-focus-visible:rounded-lg group-focus-visible:outline-2 group-focus-visible:-outline-offset-2', |
| 433 | + { 'rounded-xl': selected }, |
| 434 | + ]} |
| 435 | + data-outline |
| 436 | + ></div> |
430 | 437 | </div> |
431 | 438 | </div> |
432 | | - |
433 | | -<style> |
434 | | - [data-asset]:focus-visible > [data-outline] { |
435 | | - outline-style: solid; |
436 | | - } |
437 | | -</style> |
|
0 commit comments