Body-portal the lightbox and toast so transformed ancestors cannot trap their fixed positioning (a lightbox opened from a chat message covered only the chat column); make the toast pointer-transparent; observe the rail element's own size instead of window resizes; consume vertical wheel ticks exclusively via a non-passive listener with LINE/PAGE delta normalization; keep the start position when the rail mounts over an existing draft; honor prefers-reduced-motion for the toast, remove-control, and paging; retry loads through the guarded load effect; note the deliberate promptError re-announce; pin the intake toast in the assembled snapshot; sync the superseded multimodal note and package docs.
119 lines
2.3 KiB
CSS
119 lines
2.3 KiB
CSS
/* Thumbnail geometry mirrors DeepSeek Chat's composer rail: 64px cards with a
|
|
16px radius, remove control fully inside the card, arrows overlaid at the
|
|
edges instead of a scrollbar. */
|
|
|
|
.root {
|
|
position: relative;
|
|
min-width: 0;
|
|
}
|
|
|
|
.rail {
|
|
display: flex;
|
|
gap: 10px;
|
|
overflow-x: auto;
|
|
overflow-y: hidden;
|
|
/* Edge arrows page the overflow; the scrollbar stays hidden (both engines). */
|
|
scrollbar-width: none;
|
|
/* The rail scrolls on the composer's elevated input surface: bind the l2
|
|
pair (ui-theme styles/scrollbar.css rebinding contract) so anything that
|
|
does draw a thumb here matches the surface. */
|
|
--dsh-scrollbar-thumb: var(--dsw-alias-scrollbar-bg-l2);
|
|
--dsh-scrollbar-thumb-hover: var(--dsw-alias-scrollbar-hover-l2);
|
|
}
|
|
|
|
.rail::-webkit-scrollbar {
|
|
display: none;
|
|
}
|
|
|
|
.item {
|
|
position: relative;
|
|
flex: 0 0 64px;
|
|
width: 64px;
|
|
height: 64px;
|
|
}
|
|
|
|
.thumbnail {
|
|
width: 64px;
|
|
height: 64px;
|
|
padding: 0;
|
|
overflow: hidden;
|
|
border: 1px solid var(--dsw-alias-border-l2-darkmode-thin);
|
|
border-radius: 16px;
|
|
background: var(--dsw-alias-interactive-bg-hover);
|
|
cursor: zoom-in;
|
|
}
|
|
|
|
.thumbnail img {
|
|
display: block;
|
|
width: 100%;
|
|
height: 100%;
|
|
object-fit: cover;
|
|
}
|
|
|
|
.remove {
|
|
position: absolute;
|
|
top: 4px;
|
|
right: 4px;
|
|
z-index: 1;
|
|
display: grid;
|
|
place-items: center;
|
|
width: 18px;
|
|
height: 18px;
|
|
padding: 0;
|
|
border: none;
|
|
border-radius: 50%;
|
|
background: var(--dsw-alias-button-contrast-fill);
|
|
color: var(--dsw-alias-label-primary-inverted);
|
|
cursor: pointer;
|
|
opacity: 0;
|
|
transition: opacity 0.2s ease-in-out;
|
|
}
|
|
|
|
.item:hover .remove,
|
|
.remove:focus-visible {
|
|
opacity: 1;
|
|
}
|
|
|
|
/* Touch surfaces have no hover to reveal the control. */
|
|
@media (pointer: coarse) {
|
|
.remove {
|
|
opacity: 1;
|
|
}
|
|
}
|
|
|
|
@media (prefers-reduced-motion: reduce) {
|
|
.remove {
|
|
transition: none;
|
|
}
|
|
}
|
|
|
|
.arrow {
|
|
position: absolute;
|
|
top: 50%;
|
|
z-index: 2;
|
|
display: grid;
|
|
place-items: center;
|
|
width: 24px;
|
|
height: 24px;
|
|
padding: 0;
|
|
border: 1px solid var(--dsw-alias-border-l2-darkmode-thin);
|
|
border-radius: 999px;
|
|
background: var(--dsw-specific-input-major);
|
|
color: var(--dsw-alias-label-secondary);
|
|
box-shadow: var(--dsw-shadow-lv2);
|
|
cursor: pointer;
|
|
transform: translateY(-50%);
|
|
}
|
|
|
|
.arrow:hover {
|
|
background: var(--dsw-alias-interactive-bg-hover-solid);
|
|
}
|
|
|
|
.arrowLeft {
|
|
left: 4px;
|
|
}
|
|
|
|
.arrowRight {
|
|
right: 4px;
|
|
}
|