diff --git a/frontend/e2e-tests/components.spec.ts b/frontend/e2e-tests/components.spec.ts index da2114959d4..25b1fe08257 100644 --- a/frontend/e2e-tests/components.spec.ts +++ b/frontend/e2e-tests/components.spec.ts @@ -145,6 +145,18 @@ test("file area", async ({ page }) => { await takeScreenshot(page, _filename); }); +test("file area single", async ({ page }) => { + const helper = pageHelper(page); + await helper.selectBasicComponent("file area single"); + const element = page.getByText("Drag and drop a file here"); + // Verify is visible + await expect(element).toBeVisible(); + // Verify output + await helper.verifyOutput("None"); + + await takeScreenshot(page, _filename); +}); + test("multiselect", async ({ page }) => { const helper = pageHelper(page); await helper.selectBasicComponent("multiselect"); diff --git a/frontend/e2e-tests/py/components.py b/frontend/e2e-tests/py/components.py index 86674279b51..4dbfb9a51d1 100644 --- a/frontend/e2e-tests/py/components.py +++ b/frontend/e2e-tests/py/components.py @@ -75,8 +75,9 @@ def __(mo): @app.cell def __(mo): - file_button = lambda: mo.ui.file(kind="button") - file_area = lambda: mo.ui.file(kind="area") + file_button = lambda: mo.ui.file(kind="button", multiple=True) + file_area = lambda: mo.ui.file(kind="area", multiple=True) + file_area_single = lambda: mo.ui.file(kind="area", multiple=False) basic_ui_elements = mo.ui.dropdown( options=dict( @@ -88,6 +89,7 @@ def __(mo): "dropdown": mo.ui.dropdown, "file button": file_button, "file area": file_area, + "file area single": file_area_single, "multiselect": mo.ui.multiselect, "number": mo.ui.number, "radio": mo.ui.radio, @@ -100,11 +102,11 @@ def __(mo): ) ), ) - return basic_ui_elements, file_area, file_button + return basic_ui_elements, file_area, file_area_single, file_button @app.cell -def __(file_area, file_button, mo): +def __(file_area, file_area_single, file_button, mo): def construct_element(value): if value == mo.ui.array: return mo.ui.array([mo.ui.text(), mo.ui.slider(1, 10), mo.ui.date()]) @@ -156,6 +158,8 @@ def construct_element(value): return file_button() elif value == file_area: return file_area() + elif value == file_area_single: + return file_area_single() elif value == mo.ui.form: return mo.ui.text_area(placeholder="...").form() elif value == mo.ui.multiselect: diff --git a/frontend/src/plugins/impl/FileUploadPlugin.tsx b/frontend/src/plugins/impl/FileUploadPlugin.tsx index a4f4921c0c8..e0a7d1a7516 100644 --- a/frontend/src/plugins/impl/FileUploadPlugin.tsx +++ b/frontend/src/plugins/impl/FileUploadPlugin.tsx @@ -211,7 +211,7 @@ export const FileUpload = (props: FileUploadProps): JSX.Element => { Uploaded{" "} - {value.length} {value.length > 1 ? "files" : "file"}. + {value.length} {value.length === 1 ? "file" : "files"}. @@ -232,7 +232,9 @@ export const FileUpload = (props: FileUploadProps): JSX.Element => { } const label = - props.label ?? "Drag and drop files here, or click to open file browser"; + props.label ?? + `Drag and drop ${multiple ? "files" : "a file"} here, or click to open file browser`; + return (
@@ -284,7 +286,7 @@ export const FileUpload = (props: FileUploadProps): JSX.Element => { Uploaded{" "} - {value.length} {value.length > 1 ? "files" : "file"}. + {value.length} {value.length === 1 ? "file" : "files"}. @@ -294,7 +296,7 @@ export const FileUpload = (props: FileUploadProps): JSX.Element => { className={cn("text-destructive", "hover:underline")} onClick={() => setValue([])} > - Click to clear files. + Click to clear {multiple ? "files" : "file"}.
diff --git a/frontend/src/stories/file-upload.stories.tsx b/frontend/src/stories/file-upload.stories.tsx index d1a14201802..efab5f5a5b5 100644 --- a/frontend/src/stories/file-upload.stories.tsx +++ b/frontend/src/stories/file-upload.stories.tsx @@ -65,3 +65,33 @@ export const AcceptTxtOnlyButton = { name: "Accept .txt only, button", }; + +export const SingleFileArea = { + render: () => ( + null} + /> + ), + + name: "Single file, area", +}; + +export const SingleFileButton = { + render: () => ( + null} + /> + ), + + name: "Single file, button", +};