Komponenter
File upload
File upload er et skjemaelement for å laste opp filer.
File upload er under utvikling. Har du tilbakemelding eller innspill, meld fra på Github eller i Slack.
<ds-field class="ds-field">
<label class="ds-label">Last opp profilbilde</label>
<div data-field="description">Filen må være i csv-format og mindre enn 2MB</div>
<div class="ds-file-upload">
<div data-field="description">Slipp fil her</div>
<span class="ds-button" data-variant="secondary">Last opp fil</span>
<input type="file"/>
</div>
</ds-field>const Preview = () => ( <Field> <Label>Last opp profilbilde</Label> <Field.Description> Filen må være i csv-format og mindre enn 2MB </Field.Description> <EXPERIMENTAL_FileUpload> <Field.Description>Slipp fil her</Field.Description> <Button asChild data-variant='secondary'> <span>Last opp fil</span> </Button> <input type='file' /> </EXPERIMENTAL_FileUpload> </Field> ); render(<Preview />)
Bruk
Plasser File upload inni en field med en label slik at opplastingsområdet får en tilgjengelig ledetekst.
Bruk klassen ds-file-upload på et element som inneholder en <input type="file">. Inputen blir lagt oppå hele området slik at hele flaten blir klikkbar.
<ds-field class="ds-field">
<label class="ds-label">Last opp fil</label>
<div class="ds-file-upload">
<p class="ds-paragraph" data-field="description">Slipp fil her</p>
<p class="ds-paragraph" data-field="description">Filen må være mindre enn 2MB</p>
<span class="ds-button" data-variant="secondary">Last opp fil</span>
<input type="file" title="" />
</div>
</ds-field>
For å gjøre området skrivebeskyttet, sett readonly på inputen. Komponenten bytter da automatisk til en nøytral fargeskala og deaktiverer interaksjon.
CSS-variabler og data-attributter
File upload bruker egne CSS-variabler for å styre blant annet bakgrunn, kantlinje, ikon og luft. Disse kan overstyres på .ds-file-upload.
| Navn | Verdi |
|---|---|
| --dsc-file-upload-background | var(--ds-color-surface-default) |
| --dsc-file-upload-background--hover | var(--ds-color-surface-tinted) |
| --dsc-file-upload-border-color | var(--ds-color-border-default) |
| --dsc-file-upload-border-radius | var(--ds-border-radius-md) |
| --dsc-file-upload-border-style | dashed |
| --dsc-file-upload-border-style--hover | dashed |
| --dsc-file-upload-border-width | calc(max(2px, .125rem)) |
| --dsc-file-upload-color | currentcolor |
| --dsc-file-upload-icon-color | var(--ds-color-text-subtle) |
| --dsc-file-upload-icon-size | var(--ds-size-8) |
| --dsc-file-upload-icon-url | url('data |
| --dsc-file-upload-icon-url--readonly | url('data |
| --dsc-file-upload-padding | var(--ds-size-7) var(--ds-size-6) |
| Navn | Verdi |
|---|---|
| data-field | description |
React
import { EXPERIMENTAL_FileUpload as FileUpload, Field, Label, Button } from '@digdir/designsystemet-react';
<Field>
<Label>Last opp fil</Label>
<FileUpload>
<Field.Description>Slipp fil her</Field.Description>
<Field.Description>
Filen må være i csv-format og mindre enn 2MB
</Field.Description>
<Button asChild data-variant='secondary'>
<span>Last opp fil</span>
</Button>
<input type="file" accept=".csv" />
</FileUpload>
</Field>
react-dropzone
react-dropzone er et populært bibliotek for å lage filopplastingskomponenter i React. Her har du et eksempel på hvordan du kan bruke react-dropzone sammen med FileUpload.
<div style="min-width:300px">
<ds-field class="ds-field" role="presentation" tabIndex="0">
<label class="ds-label">Upload profile picture</label>
<div class="ds-file-upload">
<div data-field="description">Drop file(s) or click to upload</div>
<div data-field="description">
File must be
<code>.svg</code>,
<!-- -->
3
<!-- -->
of
<!-- -->
<!-- -->
3
<!-- -->
files remaining
</div>
<span class="ds-button" data-variant="secondary">Upload file</span>
<input
accept="image/svg+xml,.svg"
multiple=""
type="file"
aria-label="file upload"
style="border:0;display:block;height:0;margin:0;max-width:0;opacity:0;overflow:hidden;padding:0;width:0"
tabindex="-1"
aria-invalid="false"
/>
</div>
</ds-field>
</div>const ReactDropZoneExample = () => { const MAX_FILES = 3; const [files, setFiles] = useState<File[]>([]); const [rejected, setRejected] = useState<FileRejection[]>([]); const isReadOnly = files.length >= MAX_FILES; const { getRootProps, getInputProps, isDragActive, isDragReject } = useDropzone({ onDropAccepted: (newFiles) => { setFiles((prev) => { const remaining = MAX_FILES - prev.length; return [...prev, ...newFiles.slice(0, remaining)]; }); }, onDropRejected: (rej) => { setRejected((prev) => [...prev, ...rej]); }, accept: { 'image/svg+xml': ['.svg'], }, maxFiles: MAX_FILES, disabled: isReadOnly, }); return ( <div style={{ minWidth: '300px' }}> {/* When using react-dropzone, it is important to apply the getRootProps to the Field component and not the FileUpload component so screenreaders see the Label. This should be noted in the docs */} <Field {...getRootProps()}> <Label>Upload profile picture</Label> <EXPERIMENTAL_FileUpload> {isReadOnly && ( <> <CircleSlashIcon aria-hidden='true' /> <Field.Description> You can not upload more files </Field.Description> </> )} {!isReadOnly && ( <> {isDragReject && <CircleSlashIcon aria-hidden='true' />} <Field.Description> {isDragReject ? 'File type not accepted' : isDragActive ? 'Drop file(s) here' : 'Drop file(s) or click to upload'} </Field.Description> <Field.Description> File must be <code>.svg</code>, {MAX_FILES - files.length} of{' '} {MAX_FILES} files remaining </Field.Description> <Button asChild data-variant='secondary'> <span>Upload file</span> </Button> </> )} <input {...getInputProps({ readOnly: isReadOnly, 'aria-invalid': isDragReject, })} /> </EXPERIMENTAL_FileUpload> </Field> {files.length > 0 && ( <> <p>Accepted files</p> <ul> {files.map((file) => ( <li key={`${file.name}-${file.lastModified}`}>{file.name}</li> ))} </ul> </> )} {rejected.length > 0 && ( <> <p>Rejected files</p> <ul> {rejected.map(({ file, errors }) => ( <li key={`${file.name}-${file.lastModified}`}> {file.name} — {errors.map((e) => e.message).join(', ')} </li> ))} </ul> </> )} </div> ); }; render(<ReactDropZoneExample />)