Verwende die echten ax-Tokens aus Aksel v8, die native Tabellendichte und die semantische Kopfzeilenstruktur. Sortiere und wähle fiktive Folgedatensätze aus und vergleiche dabei helle und dunkle Designs.
Native Tabelle CSS aus Aksel 8.18.0 und Tokens mit semantischem HTML; lokaler Sortier- und Auswahlcode sowie expliziter Arial-Fallback. · Implementierungsreferenz
02
Designreferenz des Designsystems Aksel
Untersuchte native Stylesheet-Datei von @navikt/ds-css 8.18.0 sowie aktuelle v8-Dokumentation. Werte für helle und dunkle Darstellung sind entsprechend festgelegt; in der Vorschau werden entfernte Schriftarten durch Arial ersetzt und die ursprünglichen Beispieldatensätze verwendet.
Aksel v8 verwendet --ax-* Tokens und .aksel-Komponentenklassen. Laut Migrationsleitfaden funktionieren die alten .navds-Klassen nicht mehr und komponentenspezifische Tokens wurden entfernt. Ein Tutorial auf Grundlage eines älteren Screenshots kann daher plausibel wirken, aber fehlerhafte Implementierungshinweise enthalten.
Diese Seite bindet das native CSS auf Version 8.18.0 fest und enthält die passende Installation von React. Die Vorschau verwendet geprüfte native Tabellenklassen mit gewöhnlichem HTML; die Anwendung mit JavaScript übernimmt Auswahl und Sortierung. Es wird nicht behauptet, dass durch das Herunterladen eines Stylesheets eine Tabelle von React erzeugt wird.
Designsystem Aksel: Typografierollen und Laden der Schriftarten
Für das Fett-Token den Wert 600 verwenden
Die Token-Referenz definiert Source Sans 3, Source Sans Pro, Arial und sans-serif als Schriftfamilie. Für Regular gilt 400, für das benannte Fett-Token 600. Die Schriftgrößen für Fließtext umfassen 14, 16, 18 und 20px; die Überschriftenrollen reichen bis 24, 28, 32 und 40px.
In der lokalen Vorschau wird das Schriftart-Token auf Arial gesetzt und die geerbte Schriftart explizit überschrieben, sodass keine Schriftart aus dem Internet geladen wird. Das ist eine offengelegte Fallback-Entscheidung und keine Behauptung, Arial sei die primäre Schriftart von Aksel. Die Textgrößen der Komponenten werden weiterhin von CSS festgelegt.
--ax-space-16 entspricht 1rem und --ax-space-24 entspricht 1.5rem. Die v8-Syntax für Primitive folgt diesen Namen: padding="space-16" und gap={{xs:"space-8",md:"space-16"}}. Eine ältere numerische Angabe für den Abstand wird nicht ohne Prüfung der Migrationshinweise übernommen.
Zu den dokumentierten Radiusrollen gehören 2, 4, 8, 12 und 16px sowie full. In der Vorschau bleibt die native Tabellengestaltung erhalten; um die Steuerelemente der Anwendung wird space-24 verwendet. Die Lesebreite von 64rem ist eine lokale Entscheidung; die Breakpoint-Werte stammen aus dem untersuchten Stylesheet.
Die Rolle beibehalten, nicht einen einzelnen Hex-Wert
Im nativen Stylesheet wird --ax-text-neutral zu neutral-1000 aufgelöst: im hellen Modus zu #202733 und im dunklen Modus zu #dfe1e5. --ax-bg-default ändert sich von Weiß zu #0e151f. Würde der helle Textwert in einem dunklen Container fest codiert, ginge die Zuordnung über die Rollen verloren.
In der Vorschau wird die Theme-Klasse .light/.dark gewechselt; die Streifen-, Rahmen- und Markierungsfarben der Tabelle folgen den offiziellen Tokens. Für die Auswahl bleiben ein aktiviertes Kontrollkästchen und eine sichtbare Anzahl erhalten. Eine eingefärbte Zeile allein ist keine Auswahloberfläche.
Die native Tabelle hat eigene Klassen für Kopf, Tabellenkörper, Zeile, Kopfzelle und Datenzelle. Das entsprechende React-Muster verwendet Table.Header, Table.Body, Table.Row, Table.HeaderCell und Table.DataCell. Die Referenzspalte ist eine Zeilenüberschrift, und für jede Spaltenüberschrift gilt scope=col.
Die Beschriftung benennt die Datensammlung. Wartezeiten sind Mengenangaben und werden rechtsbündig ausgerichtet; Referenzkennungen bleiben linksbündig. Bei schmalen Ansichten bleibt die Tabelle in einem beschrifteten, per Tastatur fokussierbaren Bereich horizontal scrollbar. So bleiben die Tabellenbeziehungen erhalten, statt die Zeilen in kartenähnliche Elemente umzuwandeln.
Verwende Kopfzellen sowohl für Spaltenbeschriftungen als auch für Zeilenkennungen.
Mengenangaben rechtsbündig ausrichten, Postleitzahlen und Kennungen dagegen nicht.
Eine Beschriftung sorgt für einen aussagekräftigen Namen der Tabelle.
Wenn die Dichte geändert wird, ändert sich das Padding
In der untersuchten nativen CSS verwenden mittelgroße Zellen vertikal space-12 und horizontal space-8. Kleine Zellen verwenden vertikal space-4, große vertikal space-16. Der Dichtewähler ändert die native Modifier-Klasse. Die Schriftgröße des Fließtexts wird nicht verkleinert, um mehr Informationen in den sichtbaren Bereich zu zwingen.
Die Kopfzeile „Wartetage“ ist eine native Sortierschaltfläche. Ihr Handler sortiert numerische Werte und aktualisiert aria-sort für diese Kopfzeile. Diese Umwandlung liegt in der Verantwortung der Anwendung: Auch React API stellt den Sortierstatus und onSortChange bereit, statt beliebige Datensätze automatisch zu sortieren.
Jede Zeile mit einem eigenen Steuerelement versehen
Die Table-Dokumentation weist darauf hin, dass onRowClick allein nicht mit der Tastatur bedienbar ist. Das Beispiel stellt daher für jeden Datensatz ein beschriftetes Kontrollkästchen sowie ein Kontrollkästchen zum Auswählen aller Datensätze bereit. Das Kontrollkästchen für die Gesamtauswahl erhält den unbestimmten Zustand, wenn nur einige Zeilen ausgewählt sind.
Beim Sortieren bleibt die Auswahl anhand der stabilen Referenz-ID erhalten. Als Auswahl-Schlüssel wird nie der aktuelle Zeilenindex verwendet, da sich die Markierung sonst bei einer Änderung der Reihenfolge auf einen anderen Datensatz verschieben würde. Die Anzahl der ausgewählten Datensätze wird in einem höflichen Statusbereich aktualisiert. Ausgewählte Datensätze werden an keine Stelle gesendet.
Installieren Sie @navikt/ds-react und @navikt/ds-css in derselben Version und importieren Sie die CSS einmal in der Nähe des Anwendungsstamms. Das Paket enthält bereits Tokens. Die offizielle Anleitung zum CSS-Import unterstützt auch einzelne globale und Komponenten-Dateien. Baseline ist jedoch erforderlich, und Schriftarten sowie Tokens müssen bereitgestellt oder ausdrücklich ersetzt werden.
Aksel verwendet Ebenen in CSS. Vermeiden Sie breite, nicht in Ebenen eingebundene Selektoren, die versehentlich die Komponentenstile überschreiben. Benutzerdefinierte Anwendungslayouts gehören in eigene Klassen. Die eigenständige Vorschau verwendet lokal versionierte CSS und eine bewusst ersetzte Schriftart. Das React-Beispiel ist ein separater, anhand der Quelle geprüfter Integrationsweg.
Die Pakete React und CSS gemeinsam versionieren.
Das Stylesheet einmal importieren und semantische Table-Kindelemente rendern.
Sortierung und Auswahl im Anwendungsstatus verwalten.
Theme-Wechsel, Tastaturbedienung und den schmalen Scrollbereich prüfen.
Das vollständige Dokument enthält Layout, Steuerelemente und Initialisierung. Entpacken Sie das verknüpfte Beispielarchiv, um die exakten relativen Vendor-Assets zu erhalten, und stellen Sie es anschließend über HTTP bereit.
html
<!doctype html><html lang="en"><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Aksel table workbench</title><link rel="stylesheet" href="vendor/aksel-8.18.0/index.css"><style>:root{--ax-font-family:Arial,sans-serif}body,body *,body *:before,body *:after{font-family:Arial,sans-serif!important}body{background:var(--ax-bg-default);color:var(--ax-text-neutral);font-size:18px;line-height:1.5}main{max-width:64rem;padding:32px 24px;margin:auto}h1{font-size:32px;font-weight:600;line-height:1.25;margin:16px 0 24px}p{margin:16px 0}.toolbar{display:flex;gap:24px;flex-wrap:wrap;padding:24px;background:var(--ax-bg-sunken);margin:24px 0}select{font-size:16px;padding:8px;background:var(--ax-bg-input);color:var(--ax-text-neutral);border:1px solid var(--ax-border-neutral)}label{font-size:16px;display:flex;gap:8px;align-items:center}.scroll{overflow-x:auto}table{min-width:38rem}caption{text-align:left;font-weight:600;margin-bottom:16px}input[type=checkbox]{width:20px;height:20px;accent-color:var(--ax-bg-accent-strong);cursor:pointer}small{font-size:14px;display:block;margin-top:24px;color:var(--ax-text-neutral-subtle)}:focus-visible{outline:3px solid var(--ax-border-focus);outline-offset:3px}@media(max-width:767px){main{padding:24px 16px}.toolbar{padding:16px;gap:16px}h1{font-size:28px}}</style><body class="light"><main><p>AKSEL v8 · NATIVE TABLE CSS</p><h1>Follow-up record workbench</h1><p>Compare density and theme while sorting and selecting fictional records. Selection follows each reference when the rows move.</p><div class="toolbar"><label>Density <select id="density"><option value="medium">Medium</option><option value="small">Small</option><option value="large">Large</option></select></label><label>Theme <select id="theme"><option value="light">Light</option><option value="dark">Dark</option></select></label></div><p id="selection" role="status">0 records selected</p><div class="scroll" tabindex="0" role="region" aria-label="Fictional follow-up records, horizontally scrollable"><table class="aksel-table aksel-table--zebra-stripes" id="records"><caption>Fictional follow-up records</caption><thead class="aksel-table__header"><tr class="aksel-table__row"><th class="aksel-table__header-cell" scope="col"><input id="all" type="checkbox" aria-label="Select all records"></th><th class="aksel-table__header-cell" scope="col">Reference</th><th class="aksel-table__header-cell" scope="col">Next activity</th><th class="aksel-table__header-cell" id="sort-header" scope="col" aria-sort="ascending"><button id="sort" type="button" class="aksel-table__sort-button">Waiting days ↑</button></th></tr></thead><tbody class="aksel-table__body" id="rows"></tbody></table></div><small>OpenDesign specimen using native Aksel 8.18.0 CSS and an explicit Arial fallback. Fictional data, no NAV identity or external actions.</small></main><script>const data=[{id:'DEMO-204',activity:'Confirm appointment preference',days:4},{id:'DEMO-218',activity:'Read the submitted example note',days:12},{id:'DEMO-231',activity:'Arrange an example callback',days:7}];let ascending=true;const selected=new Set(),all=document.querySelector('#all');function render(){const body=document.querySelector('#rows');body.replaceChildren();for(const r of [...data].sort((a,b)=>ascending?a.days-b.days:b.days-a.days)){const tr=document.createElement('tr');tr.className='aksel-table__row'+(selected.has(r.id)?' aksel-table__row--selected':'');const td=document.createElement('td');td.className='aksel-table__data-cell';const c=document.createElement('input');c.type='checkbox';c.setAttribute('aria-label','Select '+r.id);c.checked=selected.has(r.id);c.onchange=()=>{c.checked?selected.add(r.id):selected.delete(r.id);updateSelection();tr.classList.toggle('aksel-table__row--selected',c.checked)};td.append(c);const th=document.createElement('th');th.scope='row';th.className='aksel-table__header-cell';th.textContent=r.id;const activity=document.createElement('td');activity.className='aksel-table__data-cell';activity.textContent=r.activity;const days=document.createElement('td');days.className='aksel-table__data-cell aksel-table__data-cell--align-right';days.textContent=r.days;tr.append(td,th,activity,days);body.append(tr)}updateSelection()}function updateSelection(){all.checked=selected.size===data.length;all.indeterminate=selected.size>0&&selected.size<data.length;document.querySelector('#selection').textContent=selected.size+' records selected'}all.onchange=()=>{selected.clear();if(all.checked)data.forEach(r=>selected.add(r.id));render()};document.querySelector('#sort').onclick=()=>{ascending=!ascending;document.querySelector('#sort-header').setAttribute('aria-sort',ascending?'ascending':'descending');document.querySelector('#sort').textContent='Waiting days '+(ascending?'↑':'↓');render()};document.querySelector('#density').onchange=e=>document.querySelector('table').className='aksel-table aksel-table--zebra-stripes aksel-table--'+e.target.value;document.querySelector('#theme').onchange=e=>document.body.className=e.target.value;render();</script></body></html>
Laden Sie das vollständige Beispiel unter Sources herunter. Die README enthält den genauen lokalen Startbefehl.
Behalten Sie die Vendor-Pfade relativ zu diesem Dokument bei. Das Archiv enthält alle Assets, die in dieser Vorschau verwendet werden.
04
Aksel-Designsystem: Einrichtung des AI-Agenten
Ausgangspunkt für die Implementierung
Die native CSS 8.18.0 wird in der Vorschau lokal gerendert. Die React-Komposition wurde anhand der Quelle geprüft, aber nicht separat erstellt. Stimmen Sie die Versionen aufeinander ab. Kombinieren Sie keine navds-Klassen aus v7 mit CSS aus v8. Das vollständige ZIP mit dem funktionierenden Beispiel unter „Quellen“ enthält außerdem die exakten Abhängigkeiten der Vorschau und das vollständige Dokument. Entpacken Sie es, führen Sie in diesem Verzeichnis python3 -m http.server 8080 aus und öffnen Sie dann http://localhost:8080/nav-aksel.html. Öffnen Sie Beispiele mit Modulen nicht über file://.
Erstellen Sie eine semantische Aksel-Tabelle für v8 mit den passenden Paketen CSS/React in Version 8.18.0. Verwenden Sie eine Beschriftung, Spaltenüberschriften und Zeilenüberschriften für die Datensätze. Nutzen Sie echte ax-Tokens und Primitive-Props mit space-*. Stellen Sie numerische Sortierung mit aria-sort, eine Auswahl über stabile IDs und eine Gesamtauswahl mit unbestimmtem Zustand bereit. Verlassen Sie sich bei der Tastaturbedienung nicht auf onRowClick. Unterstützen Sie Rollen-Tokens für helle und dunkle Themes sowie einen beschrifteten horizontalen Scrollbereich auf schmalen Bildschirmen.
05
Aksel-Designsystem: Quellen und Geltungsbereich
Unabhängige Beispieldatensätze ohne NAV-Identität. Das native Stylesheet wird mit einem offengelegten Schriftart-Fallback verwendet. Sortierung, Auswahl und Layout sind Anwendungsverhalten. Es werden keine echten Leistungs- oder Falldaten angezeigt.