Add Hover gallery component (#3246)

This commit is contained in:
Paweł Kuna authored and GitHub committed 2026-10-02 13:07:05 +02:00
1 parent ace9a4f123
commit f7c848a938
21 files changed
+374

No files matched your search

+1
View File
@@ -58,6 +58,7 @@
@forward 'ui/datagrid';
@forward 'ui/empty';
@forward 'ui/grid';
@forward 'ui/hover-gallery';
@forward 'ui/icons';
@forward 'ui/images';
@forward 'ui/forms';
+11
View File
@@ -1717,6 +1717,17 @@ $status-indicator-size: 2.5rem !default;
$status-circle-size: 0.75rem !default;
// scss-docs-end status-variables
// scss-docs-start hover-gallery-variables
$hover-gallery-aspect-ratio: 1 !default;
$hover-gallery-indicator-size: 2px !default;
$hover-gallery-indicator-gap: 0.25rem !default;
$hover-gallery-indicator-padding: 0.5rem !default;
$hover-gallery-indicator-color: $white !default;
$hover-gallery-indicator-scrim-height: 40% !default;
$hover-gallery-indicator-scrim-bg: linear-gradient(to top, rgba($black, 0.32), rgba($black, 0.2) 20%, rgba($black, 0.1) 45%, rgba($black, 0.03) 75%, transparent) !default;
$hover-gallery-indicator-inactive-opacity: 0.5 !default;
// scss-docs-end hover-gallery-variables
// scss-docs-start signal-variables
$signal-size: map.get(map.get($avatar-sizes, 'xs'), size) !default;
$signal-gap-ratio: 0.1 !default;
+118
View File
@@ -0,0 +1,118 @@
@use '../config' as *;
// Every item is an equal, invisible column; hovering a column shows its image over the whole gallery
.hover-gallery {
// scss-docs-start hover-gallery-css-vars
--hover-gallery-aspect-ratio: #{$hover-gallery-aspect-ratio};
--hover-gallery-indicator-size: #{$hover-gallery-indicator-size};
--hover-gallery-indicator-gap: #{$hover-gallery-indicator-gap};
--hover-gallery-indicator-padding: #{$hover-gallery-indicator-padding};
--hover-gallery-indicator-color: #{$hover-gallery-indicator-color};
--hover-gallery-indicator-scrim-height: #{$hover-gallery-indicator-scrim-height};
--hover-gallery-indicator-scrim-bg: #{$hover-gallery-indicator-scrim-bg};
--hover-gallery-indicator-inactive-opacity: #{$hover-gallery-indicator-inactive-opacity};
// scss-docs-end hover-gallery-css-vars
position: relative;
display: flex;
aspect-ratio: var(--hover-gallery-aspect-ratio);
overflow: hidden;
}
.hover-gallery-item {
flex: 1;
img {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
pointer-events: none;
object-fit: cover;
opacity: 0;
}
&:first-child img,
&:hover img {
opacity: 1;
}
&:hover img {
z-index: 1;
}
}
// One bar per item at the bottom edge, lit for the image on display
.hover-gallery-indicators {
gap: var(--hover-gallery-indicator-gap);
padding: var(--hover-gallery-indicator-padding);
// Darkens the bottom edge so the bars stay visible on any image
&::after {
position: absolute;
inset: auto 0 0;
z-index: 1;
height: var(--hover-gallery-indicator-scrim-height);
pointer-events: none;
content: '';
background: var(--hover-gallery-indicator-scrim-bg);
}
.hover-gallery-item {
display: flex;
align-items: flex-end;
// The gap between columns must not drop the hover, so the item reaches over it
padding-inline: calc(var(--hover-gallery-indicator-gap) * 0.5);
margin-inline: calc(var(--hover-gallery-indicator-gap) * -0.5);
&::after {
position: relative;
z-index: 2;
flex: 1;
height: var(--hover-gallery-indicator-size);
content: '';
background: var(--hover-gallery-indicator-color);
opacity: var(--hover-gallery-indicator-inactive-opacity);
@include border-radius(var(--hover-gallery-indicator-size));
}
&:hover::after {
opacity: 1;
}
}
&:not(:hover) .hover-gallery-item:first-child::after {
opacity: 1;
}
}
// Without hover the same markup becomes a swipeable strip
@media (hover: none) {
.hover-gallery {
gap: 0;
padding: 0;
overflow-x: auto;
scroll-snap-type: x mandatory;
scrollbar-width: none;
}
.hover-gallery::after {
display: none;
}
.hover-gallery .hover-gallery-item {
flex: 0 0 100%;
padding: 0;
margin: 0;
scroll-snap-align: start;
img {
position: static;
opacity: 1;
}
&::after {
display: none;
}
}
}