Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(file-input): sync kode med figma design #4112

Merged
merged 6 commits into from
Sep 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 55 additions & 33 deletions packages/file-input-react/src/File.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { WithOptionalChildren } from "@fremtind/jkl-core";
import { formatBytes } from "@fremtind/jkl-formatters-util";
import { IconButton } from "@fremtind/jkl-icon-button-react";
import { CloseIcon } from "@fremtind/jkl-icons-react";
import { TrashCanIcon, SuccessIcon } from "@fremtind/jkl-icons-react";
import { SupportLabel } from "@fremtind/jkl-input-group-react";
import { useId } from "@fremtind/jkl-react-hooks";
import cn from "classnames";
Expand Down Expand Up @@ -30,43 +30,65 @@ export const File: FC<FileProps> = (props) => {
const supportId = id + "-support";

const context = useFileInputContext();
const isInFileInputContext = context !== null;

const TitleComponent = path ? "a" : "div";
const f = (
<div
id={id}
className={cn("jkl-file", {
"jkl-file--error": supportLabelType === "error",
"jkl-file--warning": supportLabelType === "warning",
})}
>
<Thumbnail fileName={fileName} fileType={fileType} file={file} path={path} state={state} />
<div className="jkl-file__file-info">
<TitleComponent href={path} target={path ? "_blank" : undefined} className="jkl-file__title">
{fileName}
</TitleComponent>
<p className="jkl-file__description">
<span>{formatBytes(fileSize)}</span>
<span className="jkl-file__description-slot">{children}</span>
</p>
</div>
const Component = path ? "a" : "div";

const hasErrorOrWarning = supportLabelType === "error" || supportLabelType === "warning";
const hasSuccess = supportLabelType === "success";

const renderFeedbackElement = () => {
if (!hasErrorOrWarning && !hasSuccess) {
return (
<SupportLabel
className="jkl-file__support-label jkl-body"
id={supportId}
label={supportLabel}
labelType={supportLabelType}
/>
);
}

if (hasSuccess) return <SuccessIcon variant="small" aria-label="Filen ble lastet opp uten feil" />;

return null;
};

const fileComponent = (
<div id={id} className="jkl-file">
<Component
className={cn("jkl-file__content", {
"jkl-file__content--error": supportLabelType === "error",
"jkl-file__content--warning": supportLabelType === "warning",
})}
href={path}
target={path ? "_blank" : undefined}
>
<Thumbnail fileName={fileName} fileType={fileType} file={file} path={path} state={state}>
{children}
</Thumbnail>
<div>
<p className="jkl-file__name">{fileName}</p>
<p className="jkl-file__description">
<span>{formatBytes(fileSize)}</span>
{renderFeedbackElement()}
</p>
{supportLabel && hasErrorOrWarning && (
<SupportLabel
className="jkl-file__support-label"
id={supportId}
label={supportLabel}
labelType={supportLabelType}
/>
)}
</div>
</Component>
{onRemove && (
<IconButton onClick={onRemove} title={`Fjern ${fileName}`}>
<CloseIcon />
<IconButton className="jkl-file__delete" onClick={onRemove} title={`Fjern ${fileName}`}>
<TrashCanIcon />
</IconButton>
)}
</div>
);

if (isInFileInputContext) {
return (
<li>
{f}
{supportLabel && <SupportLabel id={supportId} label={supportLabel} labelType={supportLabelType} />}
</li>
);
}

return f;
return context ? <li>{fileComponent}</li> : fileComponent;
};
4 changes: 2 additions & 2 deletions packages/file-input-react/src/FileInput.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ describe("FileInput", () => {
</FileInput>,
);

expect(getByText("Legg til filer")).toBeInTheDocument();
expect(getByText("Legg til fil")).toBeInTheDocument();
expect(queryByText(/^Maksimum filstørrelse er/)).not.toBeInTheDocument();
});

Expand All @@ -48,7 +48,7 @@ describe("FileInput", () => {
</FileInput>,
);

expect(getByText(/størrelse per fil/)).toBeInTheDocument();
expect(getByText(/per fil/)).toBeInTheDocument();
});

it("should pass jext-axe tests in default state", async () => {
Expand Down
12 changes: 4 additions & 8 deletions packages/file-input-react/src/FileInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,9 @@ export const FileInput = forwardRef<HTMLInputElement, FileInputProps>((props, re

const hasFiles = value.length > 0;

const descriptor = multiple ? "filer" : "fil";

if (variant === "small") {
return (
<FileInputContextProvider context={{ accept, onChange, maxSizeBytes }}>
<FileInputContextProvider context={{ accept, onChange, maxSizeBytes, files: value }}>
<FieldGroup
className={cn("jkl-file-input", "jkl-file-input--small", className, {
"jkl-file-input--has-files": hasFiles,
Expand All @@ -63,8 +61,7 @@ export const FileInput = forwardRef<HTMLInputElement, FileInputProps>((props, re
>
<Dropzone>
<div className="jkl-file-input__call-to-action">
<Input id={id} label={`Legg til ${descriptor}`} multiple={multiple} ref={ref} />
<p>Slipp {descriptor} her</p>
<Input id={id} label="Legg til fil" multiple={multiple} ref={ref} />
</div>
</Dropzone>
{value.length > 0 && <ul className="jkl-file-input__files">{children}</ul>}
Expand All @@ -74,7 +71,7 @@ export const FileInput = forwardRef<HTMLInputElement, FileInputProps>((props, re
}

return (
<FileInputContextProvider context={{ accept, onChange, maxSizeBytes }}>
<FileInputContextProvider context={{ accept, onChange, maxSizeBytes, files: value }}>
<FieldGroup
className={cn("jkl-file-input", className, {
"jkl-file-input--has-files": hasFiles,
Expand All @@ -85,10 +82,9 @@ export const FileInput = forwardRef<HTMLInputElement, FileInputProps>((props, re
<Dropzone>
{value.length > 0 && <ul className="jkl-file-input__files">{children}</ul>}
<div className="jkl-file-input__call-to-action">
{value.length === 0 && <p>Slipp {descriptor} her</p>}
<Input
id={id}
label={multiple && hasFiles ? "Legg til flere filer" : `Legg til ${descriptor}`}
label={multiple && hasFiles ? "Legg til flere filer" : "Legg til fil"}
multiple={multiple}
ref={ref}
/>
Expand Down
6 changes: 4 additions & 2 deletions packages/file-input-react/src/internal/Input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,13 @@ export const Input = forwardRef<HTMLInputElement, FileInputProps>((props, ref) =

const id = useId(idProp || "jkl-file-input", { generateSuffix: !idProp });
const maxSizeDescriptionId = id + "-description";
const descriptor = multiple ? "filer" : "fil";

const context = useFileInputContext();
if (!context) {
return <p>Input must be placed inside a FileInputContextProvider.</p>;
}
const { accept, maxSizeBytes, onChange } = context;
const { accept, maxSizeBytes, onChange, files } = context;

return (
<>
Expand Down Expand Up @@ -51,9 +52,10 @@ export const Input = forwardRef<HTMLInputElement, FileInputProps>((props, ref) =
}
}}
/>
{files.length === 0 && <p>eller slipp {descriptor} her</p>}
{typeof maxSizeBytes !== "undefined" && (
<div id={maxSizeDescriptionId} className="jkl-file-input__max-size-text">
Maks {formatBytes(maxSizeBytes)} størrelse per fil
Maks {formatBytes(maxSizeBytes)} per fil
</div>
)}
</>
Expand Down
12 changes: 9 additions & 3 deletions packages/file-input-react/src/internal/Thumbnail.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import type { WithOptionalChildren } from "@fremtind/jkl-core";
import cn from "classnames";
import React, { FC } from "react";
import { FileInputFileState } from "../types";

export interface ThumbnailProps {
export interface ThumbnailProps extends WithOptionalChildren {
fileName: string;
fileType: string;
path?: string;
Expand All @@ -11,15 +12,20 @@ export interface ThumbnailProps {
}

export const Thumbnail: FC<ThumbnailProps> = (props) => {
const { fileName, fileType, path, file, state } = props;
const { fileName, fileType, path, file, state, children } = props;

const classNames = cn("jkl-file__thumbnail", {
"jkl-file__thumbnail--selected": state === "SELECTED",
"jkl-file__thumbnail--uploading": state === "UPLOADING",
});

if (fileType.startsWith("image/")) {
return <img className={classNames} src={file ? URL.createObjectURL(file) : path} alt="" />;
return (
<div className="jkl-file__thumbnail-wrapper">
<img className={classNames} src={file ? URL.createObjectURL(file) : path} alt="" />
{children}
</div>
);
}

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { FileInputFile } from "../types";
type FileInputContext = {
accept?: "image/*" | ".pdf" | "image/*,.pdf" | HTMLInputElement["accept"];
maxSizeBytes?: number;
files: FileInputFile[];
onChange: (
e: React.ChangeEvent<HTMLInputElement> | React.DragEvent<HTMLDivElement>,
files: FileInputFile[],
Expand Down
Loading
Loading