fix(post-detail): fix carousel image centering at the actual root cause
Two prior attempts today (aabb7d3,a070b37) both failed in production despite each being verified in isolation — confirmed via DevTools that the deployed DOM/CSS exactly matched what had tested correctly, yet the real page still rendered short images pinned to the top. The real, unfixable-from-outside root cause: CarouselContent's own ref div (src/components/ui/carousel.tsx) is hardcoded to className= "overflow-hidden" with no way to reach it via props, so it never gets an explicit height — every centering attempt built on top of it (grid, flex, items-center at various levels) still bottomed out on that div having only an indefinite, percentage-against-an-auto-parent height, which is a genuinely ambiguous CSS case browsers can resolve inconsistently. Fix: give CarouselContent a new optional viewportClassName prop that reaches that specific div, and pass h-full through it from PostDetailDialog. Carousel's own root div already has a definite height (traced up through the dialog's fixed dvh values), so h-full on the ref div now resolves to a real pixel value instead of falling back to auto — eliminating the ambiguity instead of working around it. Carousel/ CarouselItem revert to plain h-full + flex items-center/justify-center, no grid trick needed anymore. Re-verified via an isolated static HTML/CSS repro (embla-free, no auth needed) before deploying this time.
This commit is contained in:
1 parent
a070b37e22
commit
4c1931fd64
2 files changed
+19
-14
No files matched your search
@@ -264,18 +264,19 @@ export function PostDetailDialog({ post, open, onClose, onDeleted }: PostDetailD
|
||||
isCarousel ? (
|
||||
<div className="relative w-full h-full">
|
||||
<AiDisclosureBadge value={post.aiDisclosure} className="h-8" />
|
||||
{/* grid items-center (not flex) on purpose: CarouselContent's own
|
||||
ref div (src/components/ui/carousel.tsx) is hardcoded to
|
||||
"overflow-hidden" with no height/flex class reaching it, so it
|
||||
never fills this element's height — shorter images in a
|
||||
mixed-aspect-ratio carousel rendered pinned to the top instead
|
||||
of centered. This is the deepest point we can attach centering
|
||||
to from outside. Grid over flex specifically because grid's
|
||||
default justify-items:stretch keeps the ref div's width at
|
||||
100% (required for embla's horizontal scroll math); flex's
|
||||
shrink-to-content main-axis default would have broken that. */}
|
||||
<Carousel setApi={setCarouselApi} className="grid h-full items-center">
|
||||
<CarouselContent className="h-full">
|
||||
{/* CarouselContent's own ref div (src/components/ui/carousel.tsx)
|
||||
was hardcoded to "overflow-hidden" with no way to give it a
|
||||
height — every className/grid/flex trick attached to its
|
||||
ancestors or CarouselItem still had nothing but an indefinite
|
||||
(percentage-against-auto-parent) height to work with at that
|
||||
div specifically, so shorter images in a mixed-aspect-ratio
|
||||
carousel rendered pinned to the top instead of centered no
|
||||
matter what. Fixed at the source via CarouselContent's new
|
||||
viewportClassName prop, which reaches that div directly —
|
||||
h-full there now resolves against Carousel's own (genuinely
|
||||
definite) height instead of falling back to auto. */}
|
||||
<Carousel setApi={setCarouselApi} className="h-full">
|
||||
<CarouselContent viewportClassName="h-full" className="h-full">
|
||||
{images.map((img) => (
|
||||
<CarouselItem key={img.id} className="basis-full h-full flex items-center justify-center">
|
||||
<BlurImage
|
||||
|
||||
@@ -132,13 +132,17 @@ function Carousel({
|
||||
)
|
||||
}
|
||||
|
||||
function CarouselContent({ className, ...props }: React.ComponentProps<"div">) {
|
||||
function CarouselContent({
|
||||
className,
|
||||
viewportClassName,
|
||||
...props
|
||||
}: React.ComponentProps<"div"> & { viewportClassName?: string }) {
|
||||
const { carouselRef, orientation } = useCarousel()
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={carouselRef}
|
||||
className="overflow-hidden"
|
||||
className={cn("overflow-hidden", viewportClassName)}
|
||||
data-slot="carousel-content"
|
||||
>
|
||||
<div
|
||||
|
||||
Reference in new issue
Block a user