import * as React from 'react'; import type { Meta, StoryObj } from '@storybook/react-vite'; import { FileIcon, ImageIcon } from 'lucide-react'; import { Upload } from './upload'; import { Progress } from '../progress/progress'; const meta = { title: 'Components/Upload', component: Upload, parameters: { layout: 'centered', docs: { description: { component: 'File picker with drag and drop. A hidden but focusable file input wrapped in a label, so the control is reachable by keyboard and announced as the file input it is. The visible surface is entirely yours. Point it at an endpoint with `action`, or take over the request with `customRequest` for signed URLs.\n\n`variant="dropzone"` (the default) is the dashed drop target; `variant="button"` is a plain trigger. CBAR lists three more types โ€” `input`, `clearable` and `paste` โ€” but each of those is its Input component with a file trigger attached, so compose them rather than reaching for a variant.', }, }, }, tags: ['autodocs'], decorators: [(Story) =>
], } satisfies Meta; export default meta; type Story = StoryObj; /** No `action` here, so nothing is sent โ€” `beforeUpload` cancels the request. */ export const Default: Story = { args: { beforeUpload: () => false }, }; /** A plain trigger, for toolbars and forms where a drop target is too heavy. */ export const ButtonVariant: Story = { args: { variant: 'button', beforeUpload: () => false }, }; export const ImagesOnly: Story = { render: () => ( false}>
Drop images here
PNG, JPG or WebP ยท up to 5 MB
), }; export const Disabled: Story = { args: { disabled: true, beforeUpload: () => false }, }; /** * A realistic flow: `beforeUpload` records the file and returns `false` so the * story stays offline, then a fake progress ticker stands in for the request. */ export const WithFileList: Story = { render: function WithFileListStory() { const [files, setFiles] = React.useState<{ name: string; percent: number }[]>([]); React.useEffect(() => { if (!files.some((f) => f.percent < 100)) return; const id = setInterval(() => { setFiles((current) => current.map((f) => (f.percent >= 100 ? f : { ...f, percent: f.percent + 20 })) ); }, 400); return () => clearInterval(id); }, [files]); return (
{ setFiles((current) => [...current, { name: file.name, percent: 0 }]); return false; }} /> {files.length > 0 && (
    {files.map((file, index) => (
  • {file.name} {file.percent}%
  • ))}
)}
); }, };