Hopp til innhold

Komponenter

DataGrid

DataGrid er for visning av datasett med høy kompleksitet, mange kolonner og interaksjon som sortering, valg, under-rader og detaljpaneler.

Bruk DataGrid når en vanlig tabell ikke strekker til. Hvis du bare trenger enkel visning av tabulær data bør du vurdere Table-komponenten.

PreviewOppdatert 22. mai 2026

Preview

Denne komponenten er under utvikling, men tilgjengelig for testing. Den vil kunne få brekkende endringer utenom major-versjoner og bør ikke brukes i produksjon.

Vi ønsker at flest mulig tester ut komponenten og kommer med tilbakemeldinger i #aksel-table på Slack (kun for Nav-ansatte) eller GitHub.

Kjente feil:

  • Høyre/venstre kantlinje mangler når man fester kolonne (stickyColumn).

Dette gjenstår:

Tabell:

  • Flere varianter/layouts (inline/panel/fullbredde etc.)
  • Innstilling for kolonne separator-strek
  • Footer-støtte
  • Aggregering av rader i kolonne (hvis vi ser behov)
  • Innebygd sortering
  • Innebygd paginering
  • Rad-gruppering
  • Virtualisering (hvis vi ser behov)
  • Celle-redigering (inline-editing)
  • Støtte for col/row span (hvis vi ser behov)
  • Markering av uleste rader

Komponenter:

  • Paginering
  • Brukerinnstillinger
  • Avansert filtrering
  • Verktøylinje for filtrering og handlinger
  • Verktøylinje for batch-handlinger på valgte rader (batch-actions)

Tilgjengelighet:

  • role=”treegrid”-implementasjon for nøstede rader
  • Validering av labeling i alle states/konfigurasjoner
  • Lokaliseringsstøtte (er nå bare tilgjengelig for NB)

Egnet til:

  • Mellomstore til store tabeller med behov for kompleks interaksjon og tastaturnavigasjon.
  • Visning av fleksible og dynamiske data med loading- og empty-states.
  • Store tabeller der festede kolonner er nødvendige.
  • Komplekse rader med ekstra detaljer eller nøstede rader.

Uegnet til:

  • Små, statiske tabeller der en enkel tabell er nok.

Eksempler

Retningslinjer

Riktig oppsett

1) Bruk stabil rad-id

Bruk alltid getRowId-prop når data kan endre rekkefølge, filtreres, pagineres etc. Da blir rendring, sortering, ekspandering og valg mer stabilt og ytelsen blir preservert.

2) Velg riktig layout

  • layout="fixed" er standard og gir forutsigbar bredde for alle kolonner.
  • layout="auto" er nyttig når innholdet bør styre kolonnebredden.

Hvis du kombinerer layout="auto" med settings.truncateContent, må celler som skal trunkeres få en eksplisitt maksbredde.

3) Radklikk vs. valg

Hvis tabellen har en handling (onRowAction) bør du ofte bruke selectionTrigger="control" slik at radklikk og -valg ikke konkurrerer om samme interaksjon.

I de tilfellene du ønsker mer kontroll kan du kansellere “eventet” slik at raden ikke blir valgt.

tsx
onRowAction={({event}) => event.preventDefault()}

Ytelse

  • Unngå å lage nye data- og columns-referanser for hver render/state-endring. Bruk stabil state eller useMemo.
  • Bruk stabile ID-er med getRowId
  • Unngå unødvendig komplekst innhold i bodyCell
  • Hvis mulig, bruk alltid paginert data hvis tilgjengelig. Man kan slippe unna med mye hvis man bare trenger å rendre ~100 celler versus 1000+.

Loading- og empty-state

DataGrid håndterer annonsering for loading-varianter. Velg en variant som passer visningen:

  • skeleton: når struktur kan vises mens innhold lastes.
  • overlay: når eksisterende data skal være synlig under oppdatering.
  • content: når du vil vise tydelig, egendefinert lastetilstand.

For tilfeller der ingen data er tilgjengelig, f. eks. ved filtrering, bør emptyContent brukes for å forteller brukeren om dette. Eksempler:

  • “Ingen data tilgjengelig…”
  • “Ingen data” + knapp for å nullstille filter
  • “Kunne ikke hente data fra server” + knapp for å laste på nytt

Figma

Komponenten i Figma er også i preview. Du må regne med at komponenten vil utforske utseende og funksjonalitet som ikke er i kode.

Tilgjengelighet

Bruk rad-overskrift

Sett isRowHeader: true på kolonnen som identifiserer raden. Dette gjør tabellen lettere å forstå ved skjermlesernavigasjon. Dette bør i de fleste tilfeller bare være én kolonne.

API

Data

tsx
data: RowT[];

Dataen som DataGrid og tabellen skal vise. Denne listen bør matche typen du gir til DataGrid.Columns<…>, men kan i praksis være en liste med arbitrær data.

Pass på at data bare endres når du ønsker at tabellen skal oppdateres. Hvis data-listen blir opprettet som et nytt objekt ved andre “state”-oppdateringer, vil dette føre til mye ekstra prosessering. I mindre tabeller vil dette ikke merkes, men kan raskt ha en effekt i større tabeller.

Columns

Kolonne-definisjonen har ansvar for å bygge opp data-modellen tabellen baserer seg på.

tsx
type PersonT = {
fistName: string;
lastName: string;
age: number;
status: string;
}
const columns: DataGrid.Columns<PersonT> = [
{
id: "firstName",
isRowHeader: true,
header: "Navn",
bodyCell: ({ firstName }) => firstName,
},
{
id: "lastName",
header: "Etternavn",
bodyCell: ({ lastName }) => lastName,
},
{
id: "age",
header: "Alder",
bodyCell: ({ age }) => `${age} år`,
align: "right"
},
{
id: "status",
header: "Status",
bodyCell: ({ status }) => <Tag>{status}</Tag>,
},
]

getRowId

Hvis getRowId ikke er satt brukes radindeks som fallback. Det fungerer for statiske lister, men gir ofte dårligere stabilitet og ytelse når data endrer rekkefølge.
Vi anbefaler derfor å bruke getRowId i de fleste tilfeller.

tsx
getRowId?: (rowData: RowT) => string;
...
<DataGrid getRowId={(row) => row.id} columns={columns} data={data}>
<DataGrid.Table />
</DataGrid>

Sortering

For å sortere rader basert på én eller flere kolonner må du

  • sette isSortable: true i kolonne-definisjonen
  • lytte på onSortOrderChange for å manuelt oppdatere rekkefølgen for innholdet i data.
tsx
sorting: {
sortOrder?: {
columnId: string;
direction: "asc" | "desc";
}[];
defaultSortOrder?: {
columnId: string;
direction: "asc" | "desc";
}[];
onSortOrderChange?: (
sortOrder: {
columnId: string;
direction: "asc" | "desc";
}[],
detail: {
columnId: string;
direction: "asc" | "desc" | "none";
},
) => void;
allowMultiSort?: boolean;
};

Merk at som standard er allowMultiSort={true}, slik at bruker kan sortere basert på flere kolonner samtidig ved å holde inne Shift og klikke på sorteringsknappen.

Vi ønsker etter hvert å bygge inn sortering slik at du ikke vil trenge å håndtere sorteringslogikken selv.

Props

DataGrid

className?

  • Type:
    string

style?

  • Type:
    CSSProperties

columns

  • Type:
    ColumnDefinitions<any>
  • Description:

    Definitions of the columns to display.

data

  • Type:
    any[]
  • Description:

    The data to display.

    Each object in the array represents a row, and the properties of the object are used to render the cells based on columnDefinitions.

getRowId?

  • Type:
    ((rowData: any) => string)
  • Description:

    Function to get unique row ID from row data.

    If not provided, the row index will be used as ID. This can cause issues if your data changes dynamically, so it's recommended to provide a stable ID if possible.

selection?

  • Type:
    SelectionProps<any>
  • Description:

    Object with props related to row selection.

isLoading?

  • Type:
    boolean
  • Default:
    false
  • Description:

    Determines if the data grid is in a loading state. See loadingContent prop on the DataGrid.Table component for display settings.

settings?

  • Type:
    DataGridSettings
  • Description:

    Settings for the data grid.

ref?

  • Type:
    Ref<HTMLDivElement>
  • Description:

    Allows getting a ref to the component instance. Once the component unmounts, React will set ref.current to null (or call the ref with null if you passed a callback ref). React Docs

DataGrid.Table

layout?

  • Type:
    "fixed" | "auto"
  • Default:
    fixed
  • Description:

    Controls table layout.

    fixed

    Gives you full control of column widths. This is required for resizable columns.

    auto

    Makes the columns resize automatically based on the content. The table will take up at least 100% of available width.

    NB: When using this with truncateContent, you have to manually set a contentMaxWidth on cells that should be truncated.

stickyHeader?

  • Type:
    boolean
  • Default:
    true
  • Description:

    Whether the header should be sticky. For this to work, you have to put the component in a flex container with a height restriction.

  • Example:
    <VStack height="100vh">
    <div>Content before DataGrid</div>
    <DataGrid>
    <DataGrid.Table />
    </DataGrid>
    <div>Content after DataGrid</div>
    </VStack>

onRowAction?

  • Type:
    (({ row, id, event, }: { row: any; id: string; event: MouseEvent<HTMLTableRowElement, MouseEvent>; }) => void)
  • Description:

    Callback invoked when a row in the table body is clicked.

    Call event.preventDefault() inside the callback to prevent the default row click behavior, such as selection.

emptyContent?

  • Type:
    ReactNode
  • Description:

    Content to render when data is empty. Rendered inside a row spanning all columns.

loadingContent?

  • Type:
    DataTableLoadingConfig
  • Default:
    {
    variant: "skeleton",
    rows: 5,
    label: "Laster innhold",
    }
  • Description:

    Configures how the table behaves during loading.

    Use variant to select the loading strategy:

    • "content" — renders custom content inside a full-width row.
    • "skeleton" — renders skeleton placeholder rows.
    • "overlay" — keeps existing data visible with a loading overlay.

subRows?

  • Type:
    SubRowsProps<any>
  • Description:

    Object with props related to nested rows (sub-rows).

detailsPanel?

  • Type:
    DetailsPanelProps<any>
  • Description:

    Object with props related to details panel. This is a panel that can be expanded below each row to show arbitrary content.

sorting?

  • Type:
    TableSortOptions
  • Description:

    Object with props related to sorting.

selectionTrigger?

  • Type:
    "row" | "control"
  • Default:
    row
  • Description:

    Determines if selection is triggered by clicking the row or the selection control (checkbox/radio).

className?

  • Type:
    string

ref?

  • Type:
    Ref<HTMLTableElement>
  • Description:

    Allows getting a ref to the component instance. Once the component unmounts, React will set ref.current to null (or call the ref with null if you passed a callback ref). React Docs