File Upload
A component that allows users to upload files.
import { defineConfig } from '@pandacss/dev'
import { createPreset } from '@park-ui/panda-preset'
export default defineConfig({
preflight: true,
presets: [
'@pandacss/preset-base',
createPreset({
accentColor: '__ACCENT_COLOR__',
grayColor: '__GRAY_COLOR__',
borderRadius: '__BORDER_RADIUS__',
}),
],
include: ['./src/**/*.{js,jsx,ts,tsx}'],
jsxFramework: '__JS_FRAMEWORK__',
outdir: 'styled-system',
})
import { parkwindPlugin } from '@park-ui/tailwind-plugin'
import type { Config } from 'tailwindcss'
const config: Config = {
content: ['./src/**/*.{astro,html,js,jsx,svelte,ts,tsx,vue}'],
theme: {
extend: {},
},
plugins: [parkwindPlugin],
parkUI: {
accentColor: '__ACCENT_COLOR__',
grayColor: '__GRAY_COLOR__',
borderRadius: '__BORDER_RADIUS__',
},
darkMode: ['class'],
}
export default config
A component that allows users to upload files.
import { Trash2Icon } from 'lucide-react'
import { Button } from '~/components/ui/button'
import * as FileUpload from '~/components/ui/file-upload'
import { IconButton } from '~/components/ui/icon-button'
export const Demo = (props: FileUpload.RootProps) => {
return (
<FileUpload.Root maxFiles={3} {...props}>
<FileUpload.Dropzone>
<FileUpload.Label>Drop your files here</FileUpload.Label>
<FileUpload.Trigger asChild>
<Button size="sm">Open Dialog</Button>
</FileUpload.Trigger>
</FileUpload.Dropzone>
<FileUpload.ItemGroup>
{(files) =>
files.map((file, id) => (
<FileUpload.Item key={id} file={file}>
<FileUpload.ItemPreview type="image/*">
<FileUpload.ItemPreviewImage />
</FileUpload.ItemPreview>
<FileUpload.ItemName />
<FileUpload.ItemSizeText />
<FileUpload.ItemDeleteTrigger asChild>
<IconButton variant="link" size="sm">
<Trash2Icon />
</IconButton>
</FileUpload.ItemDeleteTrigger>
</FileUpload.Item>
))
}
</FileUpload.ItemGroup>
</FileUpload.Root>
)
}
Insert code snippet into your project. Update import paths as needed.
import { FileUpload } from '@ark-ui/react/file-upload'
import type { ComponentProps } from 'react'
import { styled } from 'styled-system/jsx'
import { fileUpload } from 'styled-system/recipes'
import { createStyleContext } from '~/lib/create-style-context'
const { withProvider, withContext } = createStyleContext(fileUpload)
export const Root = withProvider(styled(FileUpload.Root), 'root')
export const Dropzone = withContext(styled(FileUpload.Dropzone), 'dropzone')
export const Item = withContext(styled(FileUpload.Item), 'item')
export const ItemDeleteTrigger = withContext(
styled(FileUpload.ItemDeleteTrigger),
'itemDeleteTrigger',
)
export const ItemGroup = withContext(styled(FileUpload.ItemGroup), 'itemGroup')
export const ItemName = withContext(styled(FileUpload.ItemName), 'itemName')
export const ItemPreview = withContext(styled(FileUpload.ItemPreview), 'itemPreview')
export const ItemPreviewImage = withContext(styled(FileUpload.ItemPreviewImage), 'itemPreviewImage')
export const ItemSizeText = withContext(styled(FileUpload.ItemSizeText), 'itemSizeText')
export const Label = withContext(styled(FileUpload.Label), 'label')
export const Trigger = withContext(styled(FileUpload.Trigger), 'trigger')
export interface RootProps extends ComponentProps<typeof Root> {}
export interface DropzoneProps extends ComponentProps<typeof Dropzone> {}
export interface ItemProps extends ComponentProps<typeof Item> {}
export interface ItemDeleteTriggerProps extends ComponentProps<typeof ItemDeleteTrigger> {}
export interface ItemGroupProps extends ComponentProps<typeof ItemGroup> {}
export interface ItemNameProps extends ComponentProps<typeof ItemName> {}
export interface ItemPreviewProps extends ComponentProps<typeof ItemPreview> {}
export interface ItemPreviewImageProps extends ComponentProps<typeof ItemPreviewImage> {}
export interface ItemSizeTextProps extends ComponentProps<typeof ItemSizeText> {}
export interface LabelProps extends ComponentProps<typeof Label> {}
export interface TriggerProps extends ComponentProps<typeof Trigger> {}
import { FileUpload } from '@ark-ui/solid'
import type { ComponentProps } from 'solid-js'
import { styled } from 'styled-system/jsx'
import { fileUpload } from 'styled-system/recipes'
import { createStyleContext } from '~/lib/create-style-context'
const { withProvider, withContext } = createStyleContext(fileUpload)
export const Root = withProvider(styled(FileUpload.Root), 'root')
export const Dropzone = withContext(styled(FileUpload.Dropzone), 'dropzone')
export const Item = withContext(styled(FileUpload.Item), 'item')
export const ItemDeleteTrigger = withContext(
styled(FileUpload.ItemDeleteTrigger),
'itemDeleteTrigger',
)
export const ItemGroup = withContext(styled(FileUpload.ItemGroup), 'itemGroup')
export const ItemName = withContext(styled(FileUpload.ItemName), 'itemName')
export const ItemPreview = withContext(styled(FileUpload.ItemPreview), 'itemPreview')
export const ItemPreviewImage = withContext(styled(FileUpload.ItemPreviewImage), 'itemPreviewImage')
export const ItemSizeText = withContext(styled(FileUpload.ItemSizeText), 'itemSizeText')
export const Label = withContext(styled(FileUpload.Label), 'label')
export const Trigger = withContext(styled(FileUpload.Trigger), 'trigger')
export interface RootProps extends ComponentProps<typeof Root> {}
export interface DropzoneProps extends ComponentProps<typeof Dropzone> {}
export interface ItemProps extends ComponentProps<typeof Item> {}
export interface ItemDeleteTriggerProps extends ComponentProps<typeof ItemDeleteTrigger> {}
export interface ItemGroupProps extends ComponentProps<typeof ItemGroup> {}
export interface ItemNameProps extends ComponentProps<typeof ItemName> {}
export interface ItemPreviewProps extends ComponentProps<typeof ItemPreview> {}
export interface ItemPreviewImageProps extends ComponentProps<typeof ItemPreviewImage> {}
export interface ItemSizeTextProps extends ComponentProps<typeof ItemSizeText> {}
export interface LabelProps extends ComponentProps<typeof Label> {}
export interface TriggerProps extends ComponentProps<typeof Trigger> {}
Not yet available
This step is necessary only if you do not use any of the Park UI plugins.
import { fileUploadAnatomy } from '@ark-ui/anatomy'
import { defineSlotRecipe } from '@pandacss/dev'
export const fileUpload = defineSlotRecipe({
className: 'fileUpload',
slots: fileUploadAnatomy.keys(),
base: {
root: {
display: 'flex',
flexDirection: 'column',
gap: '4',
width: '100%',
},
label: {
fontWeight: 'medium',
textStyle: 'sm',
},
dropzone: {
alignItems: 'center',
background: 'bg.default',
borderRadius: 'l3',
borderWidth: '1px',
display: 'flex',
flexDirection: 'column',
gap: '3',
justifyContent: 'center',
minHeight: 'xs',
px: '6',
py: '4',
},
item: {
animation: 'fadeIn 0.25s ease-out',
background: 'bg.default',
borderRadius: 'l3',
borderWidth: '1px',
columnGap: '3',
display: 'grid',
gridTemplateColumns: 'auto 1fr auto',
gridTemplateAreas: `
"preview name delete"
"preview size delete"
`,
p: '4',
},
itemGroup: {
display: 'flex',
flexDirection: 'column',
gap: '3',
},
itemName: {
color: 'fg.default',
fontWeight: 'medium',
gridArea: 'name',
textStyle: 'sm',
},
itemSizeText: {
color: 'fg.muted',
gridArea: 'size',
textStyle: 'sm',
},
itemDeleteTrigger: {
alignSelf: 'flex-start',
gridArea: 'delete',
},
itemPreview: {
gridArea: 'preview',
},
itemPreviewImage: {
aspectRatio: '1',
height: '10',
objectFit: 'scale-down',
width: '10',
},
},
})
Previous
EditableNext
Form Label