Skip to content
Open
Show file tree
Hide file tree
Changes from 77 commits
Commits
Show all changes
80 commits
Select commit Hold shift + click to select a range
e514100
wip FileUpload
oddvernes Feb 24, 2026
e6c2009
format
oddvernes Feb 24, 2026
fa60cdc
hover & variant
oddvernes Feb 24, 2026
c14b4c1
variant story
oddvernes Feb 24, 2026
64a26c7
link variant
oddvernes Feb 24, 2026
50e66a8
test with Field
oddvernes Feb 25, 2026
000c0a7
keyboard focusable
oddvernes Feb 25, 2026
0f227cc
rest should go to input
oddvernes Feb 25, 2026
52fb1e7
change the prop-delegation cabal
oddvernes Feb 25, 2026
aed55db
adding some state variants for development
oddvernes Feb 26, 2026
29ab539
suggested readonly style
oddvernes Feb 26, 2026
7cd6b6c
wip working example
oddvernes Feb 26, 2026
9fc9e41
functional example for testing
oddvernes Feb 27, 2026
9be2624
wider
oddvernes Feb 27, 2026
0dc9990
Merge branch 'main' into feat/fileupload
oddvernes Mar 4, 2026
db9bdb8
make input a subcomponent instead
oddvernes Mar 4, 2026
a4bec45
export FileUpload
oddvernes Mar 4, 2026
370348d
add react-dropzone as dev-dep for testing
oddvernes Mar 4, 2026
6c660bb
add react-dropzone example
oddvernes Mar 4, 2026
a49ccf2
biome
oddvernes Mar 4, 2026
db73ffb
add aria-invalid to drop-zone story
oddvernes Mar 4, 2026
8e62c14
add component variables
oddvernes Mar 4, 2026
64b8201
width
oddvernes Mar 6, 2026
6da1c27
Merge branch 'main' into feat/fileupload
oddvernes Mar 6, 2026
52db577
Merge branch 'main' into feat/fileupload
oddvernes Mar 18, 2026
cb27b35
Merge branch 'main' into feat/fileupload
oddvernes Mar 19, 2026
8e18754
Merge branch 'main' into feat/fileupload
oddvernes Mar 24, 2026
1ccb133
use overlaid input instead of label
oddvernes Mar 24, 2026
f83b66f
try with build in Field like TextField
oddvernes Mar 24, 2026
657cd61
Merge branch 'main' into feat/fileupload
oddvernes Mar 25, 2026
13a9dcd
default icon
oddvernes Mar 25, 2026
f1516e7
put field outside
oddvernes Mar 26, 2026
5bd24c7
comments
oddvernes Mar 27, 2026
e00ada6
missing export
oddvernes Mar 27, 2026
1154aaf
temp example on www for sr testing
oddvernes Mar 27, 2026
568532a
scaffold docs pages
oddvernes Mar 27, 2026
1392825
fix: simplify css, remove label as concept since we now use descripti…
eirikbacker Apr 14, 2026
52beaef
Merge branch 'main' into feat/fileupload
oddvernes Apr 16, 2026
2da494f
lockfile
oddvernes Apr 16, 2026
1154b81
changeset
oddvernes Apr 17, 2026
09028fe
remove undefined export
oddvernes Apr 17, 2026
b2b3ac9
fix type error
oddvernes Apr 17, 2026
f2b66dd
biome
oddvernes Apr 17, 2026
3379086
comment out disabled story
oddvernes Apr 17, 2026
c27713c
remove the aria-hiddens
oddvernes Apr 24, 2026
c141c31
rename Button to FakeButton
oddvernes Apr 24, 2026
209a015
fix export
oddvernes Apr 24, 2026
8fa1f93
unlink button hover
oddvernes Apr 24, 2026
a3a41b9
more types fix
oddvernes Apr 24, 2026
3000f72
Merge branch 'main' into feat/fileupload
oddvernes Apr 24, 2026
7e16b9f
biome
oddvernes Apr 24, 2026
b0d5599
Merge branch 'main' into feat/fileupload
oddvernes Apr 27, 2026
807cc54
fix lock
oddvernes Apr 27, 2026
bd4a120
updated readonly styles
oddvernes Apr 27, 2026
42ac2c0
Merge branch 'main' into feat/fileupload
oddvernes Apr 28, 2026
07ff8ec
Merge branch 'main' into feat/fileupload
oddvernes Apr 29, 2026
4edd5dd
remove comments
oddvernes Apr 29, 2026
d51f695
Merge branch 'main' into feat/fileupload
Barsnes Jun 15, 2026
3398f68
fix lockfile
Barsnes Jun 15, 2026
e1977b5
Merge branch 'main' into feat/fileupload
Barsnes Jun 16, 2026
043e6fc
update docs and misc
Barsnes Jun 16, 2026
2af1821
remove dropzone
Barsnes Jun 16, 2026
57f3171
dont use code blocks
Barsnes Jun 16, 2026
76b1773
two words
Barsnes Jun 16, 2026
a37fd0c
update
Barsnes Jun 16, 2026
5d35fe7
update guidelines and text chapter
mrosvik Jun 16, 2026
13770e6
update avoid-section
mrosvik Jun 16, 2026
62bf8c0
add file upload preview img
mrosvik Jun 16, 2026
d69efa0
fix typo in code example
mimarz Jun 17, 2026
6076bab
Merge branch 'main' into feat/fileupload
mimarz Jun 17, 2026
51a6c8b
format svg
mimarz Jun 17, 2026
db7641d
Merge branch 'main' into feat/fileupload
mrosvik Jun 18, 2026
c30201d
Merge branch 'main' into feat/fileupload
Barsnes Jun 19, 2026
723dabc
add suppressHydrationWarning
Barsnes Jun 22, 2026
e19ebe5
Merge branch 'main' into feat/fileupload
Barsnes Jun 22, 2026
4eb670c
Merge branch 'main' into feat/fileupload
mimarz Jun 24, 2026
a93af65
Merge branch 'main' into feat/fileupload
mimarz Jun 25, 2026
01ef6ea
Merge branch 'main' into feat/fileupload
mimarz Jun 29, 2026
6aadd91
Merge branch 'main' into feat/fileupload
mimarz Jun 29, 2026
fc9e4c3
Merge branch 'main' into feat/fileupload
mimarz Jun 29, 2026
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
5 changes: 5 additions & 0 deletions .changeset/clear-clubs-talk.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@digdir/designsystemet-react": minor
---

**New experimental component**: `FileUpload`. Use it by importing `EXPERIMENTAL_FileUpload` from `@digdir/designsystemet-react`.
5 changes: 5 additions & 0 deletions .changeset/quick-files-upload.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@digdir/designsystemet-css": minor
---

**file-upload**: New experimental component. Style with the `ds-file-upload` class.
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<Alert data-color="warning">
We are working to improve the accessibility documentation for this component. If you have questions or see something that should be prioritised, please contact us on [Github](https://github.com/digdir/designsystemet/issues/new?template=1bug_report.yml) or [Slack](https://designsystemet.no/slack).
</Alert>

File upload must always have a visible `Label` associated with it through `Field`, so that screen readers can communicate what should be uploaded. Use `FileUpload.Description` to describe allowed file formats and sizes, so the user receives this information before uploading.
51 changes: 51 additions & 0 deletions apps/www/app/content/components/file-upload/en/code.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<Alert data-color="warning">
File upload is under development. If you have feedback or suggestions, please report them on [Github](https://github.com/digdir/designsystemet/issues/new?template=BLANK_ISSUE&title=Feedback:%20FileUpload) or in [Slack](https://designsystemet.no/slack).
</Alert>

<Story story="PreviewEn" defaultOpen/>

## Usage

Place File upload inside a [field](/en/components/docs/field/code) with a [label](/en/components/docs/label/code) so the upload area gets an accessible label.

In plain HTML, use the class `ds-file-upload` on an element that contains an `<input type="file">`. The input is placed on top of the whole area so the entire surface becomes clickable.

```html
<ds-field class="ds-field">
<label class="ds-label">Upload file</label>
<div class="ds-file-upload">
<p class="ds-paragraph" data-field="description">Drop file here</p>
<input type="file" title="" />
</div>
</ds-field>
```

To make the area read-only, set `readonly` on the input. The component then automatically switches to a neutral color scale and disables interaction.

## CSS variables and data attributes

File upload uses its own CSS variables to control things like background, border, icon and spacing. These can be overridden on `.ds-file-upload`.

<CssVariables />

<CssAttributes />

## React

```tsx
import { EXPERIMENTAL_FileUpload as FileUpload, Field, Label } from '@digdir/designsystemet-react';

<Field>
<Label>Upload file</Label>
<FileUpload>
<FileUpload.Description>Drop file here</FileUpload.Description>
<FileUpload.Description>
File must be in csv format and less than 2MB
</FileUpload.Description>
<FileUpload.FakeButton>Upload file</FileUpload.FakeButton>
<FileUpload.Input accept=".csv" />
</FileUpload>
</Field>
```

<ReactComponentDocs />
44 changes: 44 additions & 0 deletions apps/www/app/content/components/file-upload/en/overview.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
---
search_terms: file upload, upload file, attachment, drag and drop, fileupload, file input, dropzone
---

<Alert data-color="warning">
File upload is under development. If you have feedback or suggestions, please report them on [Github](https://github.com/digdir/designsystemet/issues/new?template=BLANK_ISSUE&title=Feedback:%20FileUpload) or in [Slack](https://designsystemet.no/slack).
</Alert>

<Story story="PreviewEn" />

File upload is a form element used to upload files. The component combines a drag-and-drop area with a regular file picker, so the user can select files either by clicking or by dropping them into the area.

If you need advanced file handling with per-file upload status, you must build this yourself around the component.

**Use file upload when**
- The user needs to upload one or more files as part of a form.
- You want to support both drag-and-drop and click-to-select.

**Avoid file upload when**
- The user only needs to choose from a predefined set of options.
- You can collect the information in a simpler way without requiring file upload.

## Examples

### With description
You can provide a more detailed description inside the upload area.

<Story story="FileUploadExampleEn" />

## Guidelines
Only ask for file upload when it is necessary. If you can collect the information in a simpler way, you should do that instead.

Make sure there is always a visible label that describes what should be uploaded. Also tell the user which requirements apply to the files.

Always state
- which file types are allowed
- any file size limits
- how many files can be uploaded
- what the files will be used for

## Text
The button text should be short and action-oriented, for example "Choose files" or "Choose file".

Make sure error messages follow the [guidelines for error messages](/en/patterns/errors), and use specific error messages for different error situations.
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import {
EXPERIMENTAL_FileUpload,
Field,
Label,
} from '@digdir/designsystemet-react';

export 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>
<EXPERIMENTAL_FileUpload.Description>
Slipp fil her
</EXPERIMENTAL_FileUpload.Description>
<EXPERIMENTAL_FileUpload.FakeButton>
Last opp fil
</EXPERIMENTAL_FileUpload.FakeButton>
<EXPERIMENTAL_FileUpload.Input />
</EXPERIMENTAL_FileUpload>
</Field>
);

export const PreviewEn = () => (
<Field>
<Label>Upload profile picture</Label>
<Field.Description>
File must be in csv format and less than 2MB
</Field.Description>
<EXPERIMENTAL_FileUpload>
<EXPERIMENTAL_FileUpload.Description>
Drop file here
</EXPERIMENTAL_FileUpload.Description>
<EXPERIMENTAL_FileUpload.FakeButton>
Upload file
</EXPERIMENTAL_FileUpload.FakeButton>
<EXPERIMENTAL_FileUpload.Input />
</EXPERIMENTAL_FileUpload>
</Field>
);

export const FileUploadExample = () => (
<Field>
<Label>Last opp profilbilde</Label>
<Field.Description>beskrivelsestekst</Field.Description>
<EXPERIMENTAL_FileUpload>
<EXPERIMENTAL_FileUpload.Description>
Slipp fil her
</EXPERIMENTAL_FileUpload.Description>
<EXPERIMENTAL_FileUpload.Description>
Filen må være i csv-format og mindre enn 2MB
</EXPERIMENTAL_FileUpload.Description>
<EXPERIMENTAL_FileUpload.FakeButton>
Last opp fil
</EXPERIMENTAL_FileUpload.FakeButton>
<EXPERIMENTAL_FileUpload.Input />
</EXPERIMENTAL_FileUpload>
</Field>
);

export const FileUploadExampleEn = () => (
<Field>
<Label>Upload profile picture</Label>
<Field.Description>description text</Field.Description>
<EXPERIMENTAL_FileUpload>
<EXPERIMENTAL_FileUpload.Description>
Drop file here
</EXPERIMENTAL_FileUpload.Description>
<EXPERIMENTAL_FileUpload.Description>
File must be in csv format and less than 2MB
</EXPERIMENTAL_FileUpload.Description>
<EXPERIMENTAL_FileUpload.FakeButton>
Upload file
</EXPERIMENTAL_FileUpload.FakeButton>
<EXPERIMENTAL_FileUpload.Input />
</EXPERIMENTAL_FileUpload>
</Field>
);
12 changes: 12 additions & 0 deletions apps/www/app/content/components/file-upload/metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"no": {
"title": "File upload",
"subtitle": "File upload er et skjemaelement for å laste opp filer."
},
"en": {
"title": "File upload",
"subtitle": "File upload is a form element used to upload files."
},
"image": "FileUpload.svg",
"cssFile": "file-upload.css"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<Alert data-color="warning">
Vi jobber med å forbedre dokumentasjonen for tilgjengelighet på denne komponenten. Har du spørsmål eller ser noe som bør prioriteres, ta gjerne kontakt med oss på [Github](https://github.com/digdir/designsystemet/issues/new?template=1bug_report.yml) eller [Slack](https://designsystemet.no/slack).
</Alert>

File upload skal alltid ha en synlig `Label` knyttet til seg via `Field`, slik at skjermlesere kan formidle hva som skal lastes opp. Bruk `FileUpload.Description` til å beskrive tillatte filformater og størrelser, slik at brukeren får denne informasjonen før opplasting.
51 changes: 51 additions & 0 deletions apps/www/app/content/components/file-upload/no/code.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<Alert data-color="warning">
File upload er under utvikling. Har du tilbakemelding eller innspill, meld fra på [Github](https://github.com/digdir/designsystemet/issues/new?template=BLANK_ISSUE&title=Feedback:%20FileUpload) eller i [Slack](https://designsystemet.no/slack).
</Alert>

<Story story="Preview" defaultOpen/>

## Bruk

Plasser File upload inni en [field](/no/components/docs/field/code) med en [label](/no/components/docs/label/code) 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.

```html
<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>
<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`.

<CssVariables />

<CssAttributes />

## React

```tsx
import { EXPERIMENTAL_FileUpload as FileUpload, Field, Label } from '@digdir/designsystemet-react';

<Field>
<Label>Last opp fil</Label>
<FileUpload>
<FileUpload.Description>Slipp fil her</FileUpload.Description>
<FileUpload.Description>
Filen må være i csv-format og mindre enn 2MB
</FileUpload.Description>
<FileUpload.FakeButton>Last opp fil</FileUpload.FakeButton>
<FileUpload.Input accept=".csv" />
</FileUpload>
</Field>
```

<ReactComponentDocs />
44 changes: 44 additions & 0 deletions apps/www/app/content/components/file-upload/no/overview.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
---
search_terms: filopplasting, last opp fil, opplasting, vedlegg, dra og slipp, fileupload, file input, upload, dropzone
---

<Alert data-color="warning">
File upload er under utvikling. Har du tilbakemelding eller innspill, meld fra på [Github](https://github.com/digdir/designsystemet/issues/new?template=BLANK_ISSUE&title=Feedback:%20FileUpload) eller i [Slack](https://designsystemet.no/slack).
</Alert>

<Story story="Preview" />

File upload er et skjemaelement for å laste opp filer. Komponenten kombinerer et område for å dra og slippe filer med en vanlig filvelger, slik at brukeren kan velge filer enten ved å klikke eller ved å slippe dem i området.

Hvis du trenger avansert filhåndtering med opplastingsstatus per fil, må du selv bygge dette rundt komponenten.

**Bruk file upload når**
- Brukeren skal laste opp én eller flere filer som en del av et skjema.
- Du ønsker å støtte både dra-og-slipp og klikk for å velge fil.

**Unngå file upload når**
- Brukeren kun skal velge fra et forhåndsdefinert sett med alternativer.
- Du kan hente inn informasjonen på en enklere måte uten at filopplasting er nødvendig.

## Eksempel

### Med beskrivelse
Du kan gi en mer utfyllende beskrivelse inni opplastingsområdet.

<Story story="FileUploadExample" />

## Retningslinjer
Be bare om filopplasting når det er nødvendig. Hvis du kan hente inn informasjonen på en enklere måte, bør du gjøre det i stedet.

Pass på at det alltid finnes en synlig label som beskriver hva som skal lastes opp. Fortell også hvilke krav som gjelder for filene.

Oppgi alltid
- hvilke filtyper som er tillatt
- eventuelle begrensninger på filstørrelse
- hvor mange filer som kan lastes opp
- hva filene skal brukes til

## Tekst
Knappeteksten bør være kort og handlingsorientert, f.eks "Velg filer" eller "Velg fil".

Sørg for at feilmeldinger følger [retningslinjene for feilmeldinger](/no/patterns/errors), og bruk spesifikke feilmeldinger for ulike feilsituasjoner.
33 changes: 33 additions & 0 deletions apps/www/public/img/component-previews/FileUpload.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading