Closed Robbert closed 5 days ago
Groningen en Den Haag hebben veel onderzoek gedaan, het zou handig zijn om daar een implementatie van te maken.
@Robbert Kan ik ergens deze onderzoeken teruglezen/vinden?
Gebruikte styling door team van Ruben O:
BestandInvoer.tsx:
import { ChangeEvent, InputHTMLAttributes } from "react";
import { Control, Controller, FieldValues, Path } from "react-hook-form";
import { BestandWeergave } from "../../main";
export type BestandinvoerProps<TFieldValues extends FieldValues = FieldValues> = {
name: Path<TFieldValues>;
control: Control<TFieldValues>;
uploadenLabel: string;
verwijderLabel?: string;
} & InputHTMLAttributes<HTMLInputElement>;
/**
* Om er voor te zorgen dat de implementerende kant gebruik kan maken van de BestandUpload
* binnen formulieren die op verschillende wijze zijn opgezet zijn de props 'name' en
* 'control' generiek. Hierdoor wijkt het Bestandinvoer component af qua declaratie ten
* opzichte van andere componenten.
*
* Als het verwijderLabel niet meegegeven wordt, dan wordt er geen mogelijkheid tot het verwijderen van de input aangeboden.
* @type FunctionComponent<BestandinvoerProps> - Type van het component is op deze wijze
* nog steeds beschikbaar in Typescript en voor de IDE-omgeving.
*/
export const Bestandinvoer = <TFieldValues extends FieldValues>({
name,
control,
uploadenLabel,
verwijderLabel,
...options
}: BestandinvoerProps<TFieldValues>) => (
<Controller
name={name}
control={control}
render={({ field: { onChange, value } }) =>
value ? (
<BestandWeergave
{...options}
bestand={value}
verwijderFunctie={onChange}
verwijderLabel={verwijderLabel}
/>
) : (
<div>
<label>
<input
{...options}
className="bestand-upload__file"
type="file"
onChange={(event: ChangeEvent<HTMLInputElement>) => {
onChange(event.target.files![0]);
}}
value={value?.filename}
/>
<span role="button" className="bestand-upload">
{uploadenLabel}
</span>
</label>
</div>
)
}
/>
);
BestandWeergave.tsx:
import { FunctionComponent, InputHTMLAttributes } from "react";
import { ReactComponent as BestandIcon } from "../../../icons/functioneel/66-bestand-icon.svg";
type FileType = {
size: number;
name: string;
type: string;
};
export type BestandWeergaveProps = {
bestand: File | FileType;
verwijderLabel?: string;
verwijderFunctie?: () => void;
} & InputHTMLAttributes<HTMLInputElement>;
export const BestandWeergave: FunctionComponent<BestandWeergaveProps> = ({
bestand,
verwijderLabel,
verwijderFunctie,
...options
}) => {
return (
<div className="bestand-weergave" {...options}>
<BestandIcon className="bestand-weergave__icon" />
<div className="bestand-weergave__info">
<div className="bestand-weergave__bestandnaam">
<span className="bestand-weergave__bestandnaam-titel">{bestand.name}</span>
<span className="bestand-weergave__bestandnaam-metadata">
{bestand.type}, {formateerBytes(bestand.size)}
</span>
</div>
{verwijderFunctie && verwijderLabel && (
<button onClick={verwijderFunctie} className="btn btn-link">
{verwijderLabel}
</button>
)}
</div>
</div>
);
};
export const formateerBytes = (bytes: number): string => {
const kilobytes = bytes / 1000;
const megabytes = kilobytes / 1000;
return megabytes >= 1 ? `${megabytes.toFixed(1)} MB` : `${kilobytes.toFixed(1)} KB`;
};
Wij zijn momenteel wel bezig om dit bestand meerdere bestanden te laten uploaden met mogelijkheid tot compressie. Dat kunnen wij ook delen als dit af is
Bij Open Formulieren wordt zo'n component ook al gebruikt:
Design review 1
Er is column-gap
voor de afstand boven en onder de Button. Dit hoort row-gap
te zijn.
Waar komt de variant 'Met Custom Elementen Paragraaf en Accordion' vandaan?
Die verschilt redelijk ten opzichte van 'Met Custom Elementen Lijst'. Er is bijvoorbeeld een Heading 2 gebruikt en er is geen row-gap
toegepast tussen de Heading, Paragraph en Accordion.
Is het nodig om de variant 'Met Callback' in het overzicht te tonen?
Figma Deze component bestaat uit een aantal componenten: