V1.0

Base Components

File Upload

A consistent way to drag and drop, as well as browse your computer to upload a media file.

Installation

Install the following dependencies:

terminal
npm install @radix-ui/react-slot

Create a file-upload.tsx file and paste the following code into it.

/components/ui/file-upload.tsx
// AlignUI FileUpload v0.0.0
 
import * as React from 'react';
import { Slot } from '@radix-ui/react-slot';
 
import { cnExt } from '@/utils/cn';
import { PolymorphicComponentProps } from '@/utils/polymorphic';
 
const FileUpload = React.forwardRef<
  HTMLLabelElement,
  React.LabelHTMLAttributes<HTMLLabelElement> & {
    asChild?: boolean;
  }
>(({ className, asChild, ...rest }, forwardedRef) => {
  const Component = asChild ? Slot : 'label';
 
  return (
    <Component
      ref={forwardedRef}
      className={cnExt(
        'flex w-full cursor-pointer flex-col items-center gap-5 rounded-xl border border-dashed border-stroke-sub-300 bg-bg-white-0 p-8 text-center',
        'transition duration-200 ease-out',
        // hover
        'hover:bg-bg-weak-50',
        className,
      )}
      {...rest}
    />
  );
});
FileUpload.displayName = 'FileUpload';
 
const FileUploadButton = React.forwardRef<
  HTMLDivElement,
  React.HTMLAttributes<HTMLDivElement> & {
    asChild?: boolean;
  }
>(({ className, asChild, ...rest }, forwardedRef) => {
  const Component = asChild ? Slot : 'div';
 
  return (
    <Component
      ref={forwardedRef}
      className={cnExt(
        'inline-flex h-8 items-center justify-center gap-2.5 whitespace-nowrap rounded-lg bg-bg-white-0 px-2.5 text-label-sm text-text-sub-600',
        'pointer-events-none ring-1 ring-inset ring-stroke-soft-200',
        className,
      )}
      {...rest}
    />
  );
});
FileUploadButton.displayName = 'FileUploadButton';
 
function FileUploadIcon<T extends React.ElementType>({
  className,
  as,
  ...rest
}: PolymorphicComponentProps<T>) {
  const Component = as || 'div';
 
  return (
    <Component
      className={cnExt('size-6 text-text-sub-600', className)}
      {...rest}
    />
  );
}
 
export {
  FileUpload as Root,
  FileUploadButton as Button,
  FileUploadIcon as Icon,
};

Update the import paths to match your project setup.

File Format Icon

PDF
PDF
PDF
PDF
PDF
PDF
PDF
PDF
PDF
DOC
DOC
DOC
DOC
DOC
DOC
DOC
DOC
DOC

Create a file-format-icon.tsx file and paste the following code into it.

/components/ui/file-format-icon.tsx
// AlignUI FileFormatIcon v0.0.0
 
import * as React from 'react';
 
import { tv, type VariantProps } from '@/utils/tv';
 
export const fileFormatIconVariants = tv({
  slots: {
    root: 'relative shrink-0',
    formatBox:
      'absolute bottom-1.5 left-0 flex h-4 items-center rounded px-[3px] py-0.5 text-[11px] font-semibold leading-none text-static-white',
  },
  variants: {
    size: {
      medium: {
        root: 'size-10',
      },
      small: {
        root: 'size-8',
      },
    },
    color: {
      red: {
        formatBox: 'bg-error-base',
      },
      orange: {
        formatBox: 'bg-warning-base',
      },
      yellow: {
        formatBox: 'bg-away-base',
      },
      green: {
        formatBox: 'bg-success-base',
      },
      sky: {
        formatBox: 'bg-verified-base',
      },
      blue: {
        formatBox: 'bg-information-base',
      },
      purple: {
        formatBox: 'bg-feature-base',
      },
      pink: {
        formatBox: 'bg-highlighted-base',
      },
      gray: {
        formatBox: 'bg-faded-base',
      },
    },
  },
  defaultVariants: {
    color: 'gray',
    size: 'medium',
  },
});
 
function FileFormatIcon({
  format,
  className,
  color,
  size,
  ...rest
}: VariantProps<typeof fileFormatIconVariants> &
  React.SVGProps<SVGSVGElement>) {
  const { root, formatBox } = fileFormatIconVariants({ color, size });
 
  return (
    <svg
      width='40'
      height='40'
      viewBox='0 0 40 40'
      fill='none'
      xmlns='http://www.w3.org/2000/svg'
      className={root({ class: className })}
      {...rest}
    >
      <path
        d='M30 39.25H10C7.10051 39.25 4.75 36.8995 4.75 34V6C4.75 3.10051 7.10051 0.75 10 0.75H20.5147C21.9071 0.75 23.2425 1.30312 24.227 2.28769L33.7123 11.773C34.6969 12.7575 35.25 14.0929 35.25 15.4853V34C35.25 36.8995 32.8995 39.25 30 39.25Z'
        className='fill-bg-white-0 stroke-stroke-sub-300'
        strokeWidth='1.5'
      />
      <path
        d='M23 1V9C23 11.2091 24.7909 13 27 13H35'
        className='stroke-stroke-sub-300'
        strokeWidth='1.5'
      />
      <foreignObject x='0' y='0' width='40' height='40'>
        {/* eslint-disable-next-line */}
        {/* @ts-ignore */}
        <div xmlns='http://www.w3.org/1999/xhtml' className={formatBox()}>
          {format}
        </div>
      </foreignObject>
    </svg>
  );
}
 
export { FileFormatIcon as Root };

Update the import paths to match your project setup.

© 2024 AlignUI Design System. All rights reserved.