diff --git a/packages/dnb-design-system-portal/src/docs/uilib/extensions/forms/Value/Upload/Examples.tsx b/packages/dnb-design-system-portal/src/docs/uilib/extensions/forms/Value/Upload/Examples.tsx index 529e0f109dc..65b06f8f08c 100644 --- a/packages/dnb-design-system-portal/src/docs/uilib/extensions/forms/Value/Upload/Examples.tsx +++ b/packages/dnb-design-system-portal/src/docs/uilib/extensions/forms/Value/Upload/Examples.tsx @@ -524,3 +524,29 @@ export const OnFileClick = () => { ) } + +export const DisplayFileAsNonClickable = () => { + return ( + + + + ) +} diff --git a/packages/dnb-design-system-portal/src/docs/uilib/extensions/forms/Value/Upload/demos.mdx b/packages/dnb-design-system-portal/src/docs/uilib/extensions/forms/Value/Upload/demos.mdx index 023e79d3970..50d7455139c 100644 --- a/packages/dnb-design-system-portal/src/docs/uilib/extensions/forms/Value/Upload/demos.mdx +++ b/packages/dnb-design-system-portal/src/docs/uilib/extensions/forms/Value/Upload/demos.mdx @@ -54,6 +54,12 @@ import * as Examples from './Examples' +### Display files as non-clickable + +When file size is 0 or not given (`new File([], name, { type })`), the file is displayed as a span instead of an anchor. How ever, when `onFileClick` is given, the file will be clickable as a button. + + + diff --git a/packages/dnb-eufemia/src/components/upload/UploadFileListCell.tsx b/packages/dnb-eufemia/src/components/upload/UploadFileListCell.tsx index 6f0b787eea9..a2583b1fd40 100644 --- a/packages/dnb-eufemia/src/components/upload/UploadFileListCell.tsx +++ b/packages/dnb-eufemia/src/components/upload/UploadFileListCell.tsx @@ -91,7 +91,7 @@ const UploadFileListCell = ({ const { file, errorMessage, isLoading } = uploadFile const hasWarning = errorMessage != null - const imageUrl = URL.createObjectURL(file) + const imageUrl = file?.size > 0 ? URL.createObjectURL(file) : null const cellRef = useRef() const exists = useExistsHighlight(id, file) diff --git a/packages/dnb-eufemia/src/components/upload/UploadFileListLink.tsx b/packages/dnb-eufemia/src/components/upload/UploadFileListLink.tsx index 015ed24284a..6f95d5083ee 100644 --- a/packages/dnb-eufemia/src/components/upload/UploadFileListLink.tsx +++ b/packages/dnb-eufemia/src/components/upload/UploadFileListLink.tsx @@ -1,18 +1,25 @@ import React from 'react' - +import classNames from 'classnames' import Anchor from '../../components/Anchor' import Button from '../button/Button' +import Span from '../../elements/Span' import { SpacingProps } from '../space/types' import { createSpacingClasses } from '../space/SpacingUtils' -import classNames from 'classnames' export type UploadFileLinkProps = UploadFileAnchorProps & UploadFileButtonProps export const UploadFileLink = (props: UploadFileLinkProps) => { const { onClick, text, href, download, ...rest } = props - if (onClick) + + if (!onClick && !href) { + return {text} + } + + if (onClick) { return + } + return ( { }) }) + it('renders a span when file size is 0', () => { + const fileName = 'file.png' + + render( + + ) + expect(screen.queryByText(fileName).tagName).toBe('SPAN') + expect(screen.queryByText(fileName)).toHaveClass('dnb-span') + }) + + it('renders a span when file size is not given', () => { + const fileName = 'file.png' + + render( + + ) + expect(screen.queryByText(fileName).tagName).toBe('SPAN') + expect(screen.queryByText(fileName)).toHaveClass('dnb-span') + }) + + it('renders a button when file size is invalid, but onClick is given', () => { + const fileName = 'file.png' + + render( + + ) + + expect(screen.queryByText(fileName).parentElement.tagName).toBe( + 'BUTTON' + ) + }) + describe('File Anchor', () => { it('renders the anchor', () => { const fileName = 'file.png' @@ -216,13 +262,14 @@ describe('UploadFileListCell', () => { uploadFile={{ file: createMockFile(fileName, 100, 'image/png') }} /> ) - expect(screen.queryByText(fileName)).toBeInTheDocument() + expect(screen.queryByText(fileName).tagName).toBe('A') }) it('renders the anchor href', () => { const fileName = 'file.png' const mockUrl = 'mock-url' + const originalCreateObjectURL = global.URL.createObjectURL global.URL.createObjectURL = jest.fn().mockReturnValueOnce(mockUrl) render( @@ -237,6 +284,8 @@ describe('UploadFileListCell', () => { fileName ) as HTMLAnchorElement expect(anchorElement.href).toMatch(mockUrl) + + global.URL.createObjectURL = originalCreateObjectURL }) it('renders the download attribute', () => { diff --git a/packages/dnb-eufemia/src/extensions/forms/Value/Upload/Upload.tsx b/packages/dnb-eufemia/src/extensions/forms/Value/Upload/Upload.tsx index b6230b80d05..d12447ce4a5 100644 --- a/packages/dnb-eufemia/src/extensions/forms/Value/Upload/Upload.tsx +++ b/packages/dnb-eufemia/src/extensions/forms/Value/Upload/Upload.tsx @@ -125,7 +125,7 @@ function UploadFileItem( } } - const imageUrl = URL.createObjectURL(file) + const imageUrl = file?.size > 0 ? URL.createObjectURL(file) : null const text = file.name + (displaySize ? ' ' + getSize(file.size) : '') const isLoading = fileIsLoading || loading diff --git a/packages/dnb-eufemia/src/extensions/forms/Value/Upload/__tests__/Upload.screenshot.test.ts b/packages/dnb-eufemia/src/extensions/forms/Value/Upload/__tests__/Upload.screenshot.test.ts index 62a07ad84c5..24a01119b78 100644 --- a/packages/dnb-eufemia/src/extensions/forms/Value/Upload/__tests__/Upload.screenshot.test.ts +++ b/packages/dnb-eufemia/src/extensions/forms/Value/Upload/__tests__/Upload.screenshot.test.ts @@ -57,4 +57,12 @@ describe('Value.Upload', () => { }) expect(screenshot).toMatchImageSnapshot() }) + + it('have to match files as non-clickable', async () => { + const screenshot = await makeScreenshot({ + selector: + '[data-visual-test="upload-value-display-file-as-non-clickable"]', + }) + expect(screenshot).toMatchImageSnapshot() + }) }) diff --git a/packages/dnb-eufemia/src/extensions/forms/Value/Upload/__tests__/Upload.test.tsx b/packages/dnb-eufemia/src/extensions/forms/Value/Upload/__tests__/Upload.test.tsx index 00979aa7b22..b727da994fb 100644 --- a/packages/dnb-eufemia/src/extensions/forms/Value/Upload/__tests__/Upload.test.tsx +++ b/packages/dnb-eufemia/src/extensions/forms/Value/Upload/__tests__/Upload.test.tsx @@ -322,6 +322,24 @@ describe('Value.Upload', () => { }) }) + it('renders a span when file size is 0', () => { + const fileName = 'file.png' + + render( + + ) + expect(screen.queryByText(fileName).tagName).toBe('SPAN') + expect(screen.queryByText(fileName)).toHaveClass('dnb-span') + }) + describe('File Anchor', () => { it('renders the anchor', () => { const fileName = 'file.png' @@ -337,7 +355,7 @@ describe('Value.Upload', () => { ]} /> ) - expect(screen.queryByText(fileName)).toBeInTheDocument() + expect(screen.queryByText(fileName).tagName).toBe('A') }) it('executes onFileClick event when button is clicked', () => { @@ -415,6 +433,7 @@ describe('Value.Upload', () => { const fileName = 'file.png' const mockUrl = 'mock-url' + const originalCreateObjectURL = global.URL.createObjectURL global.URL.createObjectURL = jest.fn().mockReturnValueOnce(mockUrl) render( @@ -432,6 +451,8 @@ describe('Value.Upload', () => { fileName ) as HTMLAnchorElement expect(anchorElement.href).toMatch(mockUrl) + + global.URL.createObjectURL = originalCreateObjectURL }) it('renders the download attribute', () => { diff --git a/packages/dnb-eufemia/src/extensions/forms/Value/Upload/__tests__/__image_snapshots__/valueupload-have-to-match-files-as-non-clickable.snap.png b/packages/dnb-eufemia/src/extensions/forms/Value/Upload/__tests__/__image_snapshots__/valueupload-have-to-match-files-as-non-clickable.snap.png new file mode 100644 index 00000000000..8adad6e159f Binary files /dev/null and b/packages/dnb-eufemia/src/extensions/forms/Value/Upload/__tests__/__image_snapshots__/valueupload-have-to-match-files-as-non-clickable.snap.png differ