Skip to content

Refactor/upload v2#1386

Open
deepakoram-juspay wants to merge 4 commits intodevfrom
refactor/uploadV2
Open

Refactor/upload v2#1386
deepakoram-juspay wants to merge 4 commits intodevfrom
refactor/uploadV2

Conversation

@deepakoram-juspay
Copy link
Copy Markdown
Collaborator

@deepakoram-juspay deepakoram-juspay commented May 6, 2026

Summary

Screenshot 2026-05-06 at 3 40 26 PM Screenshot 2026-05-06 at 3 40 26 PM (2) Screenshot 2026-05-06 at 3 40 43 PM Screenshot 2026-05-06 at 3 40 43 PM (2)

upload refactor

Issue Ticket

Closes #1385

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented May 6, 2026

Open in StackBlitz

npm i https://pkg.pr.new/@juspay/blend-design-system@1386

commit: d03acd2

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a new UploadV2 input component (plus theming/tokens), adds documentation and automated tests, and wires the component into Storybook and the site demos as part of the “upload refactor” work (Closes #1385).

Changes:

  • Added UploadV2 component implementation with drag/drop, validation metadata (isValid/errorReason), and progress/state handling.
  • Introduced UploadV2 responsive tokens (light/dark) and registered UPLOADV2 in the theme/component token system.
  • Added tests (functional + accessibility), design docs, and Storybook/site demos for UploadV2.

Reviewed changes

Copilot reviewed 19 out of 20 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
packages/blend/lib/context/useComponentToken.ts Adds UPLOADV2 token lookup support.
packages/blend/lib/context/ThemeContext.tsx Registers UPLOADV2 in ComponentTokenType and default theme tokens.
packages/blend/lib/context/initComponentTokens.ts Ensures UPLOADV2 tokens are initialized per theme.
packages/blend/lib/components/Primitives/PrimitiveInput/PrimitiveInput.tsx Expands as typing (currently introduces an invalid 'file' option).
packages/blend/lib/components/InputsV2/UploadV2/utils.ts Adds UploadV2 helper utilities (IDs, truncation, validation messages).
packages/blend/lib/components/InputsV2/UploadV2/UploadV2.types.ts Defines UploadV2 public types/enums.
packages/blend/lib/components/InputsV2/UploadV2/UploadV2.tsx Implements the UploadV2 component and hidden native file input behavior.
packages/blend/lib/components/InputsV2/UploadV2/UploadV2.tokens.ts Defines UploadV2 token types + theme selector.
packages/blend/lib/components/InputsV2/UploadV2/UploadV2.light.tokens.ts Adds light theme token values for UploadV2.
packages/blend/lib/components/InputsV2/UploadV2/UploadV2.dark.tokens.ts Adds dark theme token values for UploadV2.
packages/blend/lib/components/InputsV2/UploadV2/UploadContainerV2.tsx Renders UploadV2 UI surface, buttons, tags, and error/progress states.
packages/blend/lib/components/InputsV2/UploadV2/index.ts Adds module exports for UploadV2.
packages/blend/Design-docs/Upload/UploadDoc.md Adds UploadV2 design/usage documentation.
packages/blend/tests/components/UploadV2/UploadV2.test.tsx Adds functional tests for file selection, validation, and removal behavior.
packages/blend/tests/components/UploadV2/UploadV2.accessibility.test.tsx Adds axe-based accessibility tests for key states.
apps/storybook/stories/components/Upload/v2/UploadV2.stories.tsx Adds Storybook stories for UploadV2 states and usage.
apps/site/src/demos/UploadV2Demo.tsx Adds a site demo/playground for UploadV2.
apps/site/src/demos/UploadDemo.tsx Updates Upload v1 demo slot rendering.
apps/site/src/demos/SidebarDemo.tsx Adds navigation to the new UploadV2 demo.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

export type InputProps = React.InputHTMLAttributes<HTMLInputElement> &
PrimitiveInputProps & {
as?: 'input' | 'textarea'
as?: 'input' | 'textarea' | 'file'
Comment on lines +126 to +141
<InputLabelsV2
tokens={tokens.topContainer as InputLabelsV2Tokens}
label={label}
sublabel={subLabel}
size={size}
state={
state === UploadState.ERROR
? InputStateV2.ERROR
: state === UploadState.DISABLED
? InputStateV2.DISABLED
: InputStateV2.DEFAULT
}
helpIconText={helpIconText}
inputId={inputId}
required={required}
/>
Comment on lines +251 to +257
aria-required={required}
aria-invalid={uploadState === UploadState.ERROR}
aria-describedby={
[description, errorText, helpIconText]
.filter(Boolean)
.join(' ') || undefined
}
Comment on lines +58 to +67
const validateFiles = (newFiles: File[]): UploadFileV2[] => {
const limit = maxFiles ?? (multiple ? undefined : 1)
const remainingSlots = limit ? limit - files.length : Infinity
let hasRejection = false

const validatedFiles: UploadFileV2[] = newFiles.map(
(file, index) => {
// Check maxFiles limit
if (limit && index >= remainingSlots) {
hasRejection = true
Comment on lines +104 to +116
useEffect(() => {
if (state === UploadState.UPLOADING) {
setUploadState(UploadState.UPLOADING)
} else if (state === UploadState.SUCCESS) {
setUploadState(UploadState.SUCCESS)
} else if (state === UploadState.ERROR) {
setUploadState(UploadState.ERROR)
} else if (disabled) {
setUploadState(UploadState.DISABLED)
} else {
setUploadState(UploadState.IDLE)
}
}, [state, disabled])
Comment on lines +131 to +137
state={
state === UploadState.ERROR
? InputStateV2.ERROR
: state === UploadState.DISABLED
? InputStateV2.DISABLED
: InputStateV2.DEFAULT
}
Comment on lines +57 to +85
// Validate files and mark with isValid flag instead of filtering
const validateFiles = (newFiles: File[]): UploadFileV2[] => {
const limit = maxFiles ?? (multiple ? undefined : 1)
const remainingSlots = limit ? limit - files.length : Infinity
let hasRejection = false

const validatedFiles: UploadFileV2[] = newFiles.map(
(file, index) => {
// Check maxFiles limit
if (limit && index >= remainingSlots) {
hasRejection = true
return {
id: `${file.name}-${file.size}-${file.lastModified}-${Date.now()}-${index}`,
file,
isValid: false,
errorReason: UploadErrorReason.MAX_FILES,
}
}

// Check maxSize
if (maxSize && file.size > maxSize) {
hasRejection = true
return {
id: `${file.name}-${file.size}-${file.lastModified}-${Date.now()}-${index}`,
file,
isValid: false,
errorReason: UploadErrorReason.OVERSIZED,
}
}
import React from 'react'
import Block from '../../Primitives/Block/Block'
import { ButtonV2, ButtonV2Size, ButtonV2Type } from '../../ButtonV2'
import { SwapIcon } from '@phosphor-icons/react/dist/ssr/Swap'
Comment on lines +156 to +157
| ResponsiveUploadV2Tokens
| ChatInputV2MobileTokensType => {
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Upload refactor

2 participants