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.
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.
onRowAction={({event}) => event.preventDefault()}Ytelse
- Unngå å lage nye
data- ogcolumns-referanser for hver render/state-endring. Bruk stabil state elleruseMemo. - 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
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å.
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.
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: truei kolonne-definisjonen - lytte på
onSortOrderChangefor å manuelt oppdatere rekkefølgen for innholdet idata.
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
loadingContentprop on theDataGrid.Tablecomponent 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.currenttonull(or call the ref withnullif 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 acontentMaxWidthon 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
datais 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
variantto 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.currenttonull(or call the ref withnullif you passed a callback ref). React Docs