/* * (c) Copyright 2026 Palantir Technologies Inc. All rights reserved. */ import type { Meta, StoryObj } from "@storybook/react-vite"; import { StoryLabel } from "@storybook-common"; import { type ChangeEvent, useCallback, useState } from "react"; import { Flex } from "@blueprintjs/labs"; import { Size } from "../../common"; import { FileInput } from "./fileInput"; const meta: Meta = { title: "Core/Form/Inputs/FileInput", component: FileInput, decorators: [ Story => ( ), ], tags: ["autodocs"], args: { text: "Choose file...", buttonText: "Browse", disabled: false, fill: false, hasSelection: false, size: "medium", }, argTypes: { text: { control: "text", }, buttonText: { control: "text", }, size: { control: "select", options: Object.values(Size), }, disabled: { control: "boolean", }, fill: { control: "boolean", }, hasSelection: { control: "boolean", }, onInputChange: { action: "inputChanged" }, // deprecated props large: { table: { disable: true } }, small: { table: { disable: true } }, }, } satisfies Meta; export default meta; type Story = StoryObj; /** * A basic file input with default styling. */ export const Default: Story = {}; /** * Use the `size` prop to adjust the file input dimensions. */ export const SizeExample: Story = { name: "Size", argTypes: { size: { table: { disable: true } }, }, render: args => ( {Object.values(Size).map(size => ( ))} ), }; /** * FileInput supports `disabled` state and `hasSelection` visual state. */ export const StateExample: Story = { name: "State", argTypes: { disabled: { table: { disable: true } }, hasSelection: { table: { disable: true } }, }, render: args => ( ), }; /** * Use the `fill` prop to make the file input expand to the full width of its container. */ export const FillExample: Story = { name: "Fill", argTypes: { fill: { table: { disable: true } }, }, decorators: [ Story => (
), ], render: args => ( ), }; /** * Customize the button text with the `buttonText` prop. */ export const ButtonTextExample: Story = { name: "Button Text", argTypes: { buttonText: { table: { disable: true } }, }, render: args => ( ), }; /** * A file input in the focused state, showing the focus ring. */ export const FocusedExample: Story = { name: "Focused", play: async ({ canvas }) => { const label = canvas.getByText("Choose file..."); const input = label.closest("label")?.querySelector("input"); if (input) { input.focus(); } }, render: args => ( ), }; /** * Interactive playground with file selection handling. */ export const Playground: Story = { render: function Render(args) { const [fileName, setFileName] = useState(null); const handleInputChange = useCallback( (e: ChangeEvent) => { const file = e.target.files?.[0]; setFileName(file?.name ?? null); args.onInputChange?.(e); }, [args], ); return ( {fileName != null && } ); }, args: { buttonText: "Browse", }, };