Saas.js logo
SlingshotUI libraries

Shadcn UI

How to use Slingshot with Shadcn

Slingshot has built-in support for Shadcn and can easily be added to your Shadcn project using the CLI.

Installation

npx shadcn@latest add "https://saas-js.dev/r/slingshot"

Usage

'use client'
 
import * as FileUpload from '@/components/ui/file-upload'
import { Button } from '@/components/ui/button'
import { Progress } from '@/components/ui/progress'
 
import { FileUploadRootProps } from '@saas-js/slingshot-react'
 
export const UploadAvatar = (props: Omit<FileUploadRootProps, 'children'>) => {
  return (
    <FileUpload.Root profile="avatar" maxFiles={1} {...props}>
      <FileUpload.Context>
        {(api) => {
          const slingshotFiles = api.slingshot.getFiles()
 
          return (
            <>
              <FileUpload.Dropzone>
                <FileUpload.Label>Drag your file(s) here</FileUpload.Label>
 
                <FileUpload.Trigger asChild>
                  <Button>Choose file(s)</Button>
                </FileUpload.Trigger>
              </FileUpload.Dropzone>
 
              <FileUpload.ItemGroup>
                {api.acceptedFiles.map((file) => {
                  const slingshotFile = api.slingshot
                    .getFiles()
                    ?.find((f) => f.name === file.name)
 
                  return (
                    <FileUpload.Item
                      key={file.name}
                      file={file}
                      className="relative items-center"
                    >
                      <FileUpload.ItemPreview type="image/*">
                        <FileUpload.ItemPreviewImage />
                      </FileUpload.ItemPreview>
                      <div className="flex flex-col flex-1">
                        <FileUpload.ItemName />
                        <FileUpload.ItemSizeText />
                      </div>
 
                      <div className="text-xs text-gray-500">
                        {slingshotFile?.progress &&
                          (slingshotFile?.status === 'done' ? (
                            <span>Done</span>
                          ) : (
                            <span>{slingshotFile?.progress}%</span>
                          ))}
                      </div>
 
                      {slingshotFile?.progress &&
                        slingshotFile?.status !== 'done' && (
                          <Progress
                            value={slingshotFile?.progress ?? 0}
                            className="absolute bottom-0 right-0 left-0 h-1"
                          />
                        )}
 
                      <FileUpload.ItemDeleteTrigger asChild>
                        <Button variant="ghost" size="icon">

                        </Button>
                      </FileUpload.ItemDeleteTrigger>
                    </FileUpload.Item>
                  )
                })}
              </FileUpload.ItemGroup>
 
              <FileUpload.HiddenInput />
 
              {slingshotFiles.map(({ url }) => (
                <input
                  key={url}
                  type="hidden"
                  name={props.profile}
                  value={url?.split('?')[0]}
                />
              ))}
            </>
          )
        }}
      </FileUpload.Context>
    </FileUpload.Root>
  )
}

On this page