import type { Meta, StoryFn } from '@storybook/react' import React from 'react' import { StoryGrid, StoryHeading, StoryPage, StoryRow, } from '../stories/StoryTable' import type { ImageItem } from '../types' import ImageAttachment from '.' const SINGLE_IMAGE = 'https://picsum.photos/seed/portrait/720/720' const STACK_IMAGES: ImageItem[] = [ { src: 'https://picsum.photos/seed/img-1/720/720', alt: 'Photo 1' }, { src: 'https://picsum.photos/seed/img-2/720/720', alt: 'Photo 2' }, { src: 'https://picsum.photos/seed/img-3/720/720', alt: 'Photo 3' }, { src: 'https://picsum.photos/seed/img-4/720/720', alt: 'Photo 4' }, { src: 'https://picsum.photos/seed/img-5/720/720', alt: 'Photo 5' }, { src: 'https://picsum.photos/seed/img-6/720/720', alt: 'Photo 6' }, ] /** * One source per aspect bucket, with intrinsic dimensions supplied so * the card resolves at first paint instead of waiting on a network * decode. Expected web cards (326×436 content box inside a 2px * frame): portrait 249×440, landscape 330×187, square 330×330, * panorama 330×69. */ const ASPECT_BUCKETS: { label: string; item: ImageItem }[] = [ { label: 'Portrait 9:16', item: { src: 'https://picsum.photos/seed/ratio-portrait/1080/1920', alt: 'Portrait photo', width: 1080, height: 1920, }, }, { label: 'Landscape 16:9', item: { src: 'https://picsum.photos/seed/ratio-landscape/1920/1080', alt: 'Landscape photo', width: 1920, height: 1080, }, }, { label: 'Square 1:1', item: { src: 'https://picsum.photos/seed/ratio-square/1200/1200', alt: 'Square photo', width: 1200, height: 1200, }, }, { label: 'Panorama 5:1', item: { src: 'https://picsum.photos/seed/ratio-panorama/3000/600', alt: 'Panoramic photo', width: 3000, height: 600, }, }, ] const meta: Meta = { title: 'MessageAttachment/Image', parameters: { layout: 'fullscreen' }, } export default meta const handleDismiss = () => { console.log('Dismissed image attachment') } /** * Single image — renders inside a chat bubble with rounded corners. * Composer / Sent / Received are all interactive: clicking opens the * built-in `ImageViewer` lightbox (full-viewport ``, image * centered at reasonable max dimensions, close + download buttons in * the chrome — Escape or backdrop click also dismiss). */ export const Single: StoryFn = () => ( } sent={ } received={ } /> ) /** * Single image, one row per aspect bucket. The image keeps its own * ratio, fitted inside a max 326×436 content box on web (309×436 * below the `sm` breakpoint) — so `object-cover` never crops. Portrait * resolves against the 440px height cap; landscape, square and * panorama against the 330px width cap. * * Sent + Received only: the composer thumbnail is a fixed square and * is unaffected by this treatment, so the Composer column is blank. */ export const SingleAspectRatios: StoryFn = () => ( {ASPECT_BUCKETS.map(({ label, item }) => ( } received={ } /> ))} ) /** Single image with an accompanying caption rendered inside the bubble. * Sent + Received only — captions are not rendered on the composer * surface (the user types them in the message input, not on the * attachment preview). */ export const SingleWithText: StoryFn = () => ( } sent={ } received={ } /> } sent={ } received={ } /> ) /** * Stacked image attachments — multiple images in one bubble laid out * in a 1 / 2 / 3 / 4-tile grid. Five or more collapse into a `+N` * overflow tile on the bottom-right. Click any tile to open the * lightbox on that specific image; the viewer becomes a carousel * (prev/next chrome, ArrowLeft / ArrowRight, and a `current / total` * counter) so the user can browse siblings without closing. * * Sent + Received only — the composer surface accepts a single image * at a time, so the Composer column is intentionally blank. */ export const Stacked: StoryFn = () => ( } sent={ } received={ } /> } sent={ } received={ } /> } sent={ } received={ } /> } received={ } /> ) /** Stacked image attachments with an accompanying caption. * Sent + Received only — see `Stacked` for the rationale. */ export const StackedWithText: StoryFn = () => ( } sent={ } received={ } /> } sent={ } received={ } /> )