Services publics et administration · Nouvelle ressource

Système de design Aksel.

Utilisez les véritables tokens ax de Aksel v8, la densité native des tableaux et la structure sémantique de leurs en-têtes. Triez et sélectionnez des dossiers de suivi fictifs tout en comparant les thèmes clair et sombre.

Guide OpenDesign8 chapitres13 référencesGuide de l’application d’origine
01

Aperçu de l’interface du système de design Aksel

Triez les délais d’attente numériques, sélectionnez des dossiers, changez la densité et comparez les rôles du thème clair et sombre.

Espace de travail des tableaux de suiviOuvrir l’exemple complet
Tableau natif Aksel 8.18.0 CSS et jetons avec HTML sémantique ; code local de tri et de sélection, et solution de repli explicite Arial. · Référence de mise en œuvre
02

Référence de conception du système de design Aksel

Feuille de style native @navikt/ds-css 8.18.0 examinée et documentation v8 actuelle. Les valeurs des modes clair et sombre sont contextualisées ; l’aperçu remplace les polices distantes par Arial et utilise les exemples de dossiers d’origine.

Typographie v8

Source
Nom / règleValeur / configurationUtilisation
--ax-font-familySource Sans 3, Source Sans Pro, Arial, sans-serifL’aperçu utilise explicitement Arial comme police de repli.
--ax-font-weight-regular / bold400 / 600Ne confondez pas le jeton nommé pour le gras avec la valeur 700.
--ax-font-size-medium / large1rem / 1.125rem16px / 18px avec la taille de base standard.
--ax-font-size-heading-xlarge / 2xlarge2rem / 2.5rem32px / 40px.

Espacement et points de rupture

Source
Nom / règleValeur / configurationUtilisation
--ax-space-8 / 16 / 24 / 320.5 / 1 / 1.5 / 2remLes noms des jetons indiquent leurs équivalents en pixels standard.
--ax-radius-2 / 4 / 8 / 12 / 162 / 4 / 8 / 12 / 16pxRôles des rayons.
sm / md / lg / xl / 2xl480 / 768 / 1024 / 1280 / 1440pxValeurs examinées dans la version de CSS correspondante.

Géométrie native des tableaux

Source
Nom / règleValeur / configurationUtilisation
Medium cell padding12px 8pxMarges intérieures verticale / horizontale par défaut.
Small / large vertical padding4px / 16pxModificateurs natifs de densité ; la marge horizontale reste à 8px.
Header divider2pxLe séparateur des lignes du corps reste à 1px.

Rôles du thème

Source
Nom / règleValeur / configurationUtilisation
--ax-bg-default#fff light / #0e151f darkSurface racine.
--ax-text-neutral#202733 light / #dfe1e5 darkValeurs neutral-1000 résolues.
--ax-bg-accent-strong#2176d4 light / #4580ca darkValeurs accent-600 résolues ; utilisez le rôle dans le code.
03

Guide complet du système de design Aksel

Un guide pratique pour choisir, appliquer et évaluer ce système dans une interface réelle.

DESIGN-nav-aksel.md

Des conseils complets, un point de départ pour la mise en œuvre et des liens vers les sources.

Télécharger le guide

Système de design Aksel : partir du contrat v8

Ne mélangez pas les anciennes classes et les nouveaux jetons

La version v8 de Aksel utilise les jetons --ax-* et les classes de composants .aksel. Le guide de migration précise que les anciennes classes .navds ne fonctionnent plus et que les jetons propres aux composants ont été supprimés. Un tutoriel basé sur une ancienne capture d’écran peut donc sembler crédible tout en donnant des conseils d’implémentation erronés.

Extrait de ce guide OpenDesign

Cette page fixe la version native de CSS à 8.18.0 et fournit l’installation correspondante de React. L’aperçu utilise les classes natives de tableau examinées, avec un HTML ordinaire ; l’application JavaScript gère la sélection et le tri. Il ne prétend pas que le téléchargement d’une feuille de style instancie un composant Table de React.

Consultez la spécification associée

Système de design Aksel : rôles typographiques et chargement des polices

Utilisez 600 pour le jeton de gras

La référence des jetons définit la pile de polices Source Sans 3, Source Sans Pro, Arial et sans-serif. Le poids normal est 400 et le jeton nommé pour le gras vaut 600. Les tailles de texte courant comprennent 14, 16, 18 et 20px ; les rôles de titre vont jusqu’à 24, 28, 32 et 40px.

L’aperçu local définit le jeton de police sur Arial et remplace explicitement toute police héritée, afin de ne faire aucune requête de police distante. Il s’agit d’un choix de police de repli déclaré, et non d’affirmer qu’Arial est la police principale du système de design Aksel. Le dimensionnement du texte des composants est toujours fourni par CSS.

Consultez la spécification associée

Système de design Aksel : espacement, rayon et mise en page

Les jetons nommés en pixels correspondent à des valeurs en rem

--ax-space-16 vaut 1rem et --ax-space-24 vaut 1.5rem. La syntaxe des primitives v8 respecte ces noms : padding="space-16" et gap={{xs:"space-8",md:"space-16"}}. Ne remplacez pas ces valeurs par une ancienne propriété d’espacement numérique sans vérifier les consignes de migration.

Les rôles de rayon documentés comprennent 2, 4, 8, 12 et 16px, ainsi que la valeur full. L’aperçu conserve la géométrie native du tableau et utilise space-24 autour des commandes de l’application. La largeur de lecture de 64rem est un choix local ; les points de rupture proviennent de la feuille de style examinée.

Consultez la spécification associée

Système de design Aksel : couleurs sémantiques adaptées au thème

Préservez le rôle, pas une valeur hexadécimale unique

La feuille de style native associe --ax-text-neutral à neutral-1000, soit #202733 en mode clair et #dfe1e5 en mode sombre. --ax-bg-default passe du blanc à #0e151f. Inscrire en dur la valeur de texte du mode clair dans un conteneur sombre annulerait la correspondance des rôles.

L’aperçu change la classe de thème .light/.dark et laisse les couleurs des bandes, des bordures et des lignes sélectionnées du tableau suivre les jetons officiels. La sélection reste indiquée par une case cochée et un compteur visible. Une ligne colorée ne suffit pas à constituer une interface de sélection.

Consultez la spécification associée

Système de design Aksel : anatomie sémantique des tableaux

Les en-têtes ne sont pas des cellules ordinaires

Le tableau natif distingue les classes d’en-tête, de corps, de ligne, de cellule d’en-tête et de cellule de données. L’équivalent de React utilise Table.Header, Table.Body, Table.Row, Table.HeaderCell et Table.DataCell. La colonne de référence est un en-tête de ligne, et chaque en-tête de colonne possède scope=col.

La légende nomme la collection. Les jours d’attente sont des quantités et sont alignés à droite ; les identifiants de référence restent alignés à gauche. À faible largeur, l’aperçu conserve le défilement horizontal dans une zone nommée qui peut recevoir le focus clavier, plutôt que de dégrader les relations du tableau pour transformer les lignes en cartes.

  • Utilisez des cellules d’en-tête pour les libellés de colonnes comme pour les identifiants de ligne.
  • Alignez à droite les valeurs quantitatives, mais pas les codes postaux ni les identifiants.
  • Ajoutez une légende pour donner un nom explicite au tableau.

Consultez la spécification associée

Système de design Aksel : densité et tri

Changer la densité modifie les marges intérieures

Dans le composant CSS natif inspecté, les cellules de densité moyenne utilisent space-12 verticalement et space-8 horizontalement. La densité faible utilise space-4 verticalement, et la densité élevée, space-16 verticalement. Le sélecteur de densité modifie la classe de modificateur native ; il ne réduit pas la taille de la police du corps pour faire tenir davantage d’informations dans la fenêtre.

L’en-tête « Jours d’attente » est un bouton de tri de style natif. Son gestionnaire trie les valeurs numériques et met à jour aria-sort sur cet en-tête. Cette transformation relève de l’application : le composant React API expose lui aussi l’état de tri et onSortChange, au lieu de trier automatiquement des enregistrements métier arbitraires.

Consultez la spécification associée

Système de design Aksel — sélection des lignes accessible au clavier

Prévoir un contrôle explicite pour chaque ligne

La documentation de Table indique que onRowClick seul ne permet pas l’accessibilité au clavier. L’exemple fournit donc une case à cocher avec libellé pour chaque référence et une case pour tout sélectionner. La case globale passe à l’état indéterminé lorsqu’une partie seulement des lignes est sélectionnée.

Le tri préserve la sélection grâce à l’identifiant stable de la référence. Il n’utilise jamais l’index actuel de la ligne comme clé de sélection, car la coche se déplacerait vers un autre enregistrement lors d’un changement d’ordre. Le nombre d’éléments sélectionnés est mis à jour dans une région de statut avec annonce polie. Aucun enregistrement sélectionné n’est envoyé ailleurs.

Consultez la spécification associée

Système de design Aksel — charger les CSS et React correspondants

Synchroniser les versions des paquets

Installez @navikt/ds-react et @navikt/ds-css à la même version, puis importez le CSS une seule fois, près de la racine de l’application. Le paquet inclut déjà les tokens de design. Le guide officiel d’importation de CSS prend également en charge les fichiers globaux et de composants importés séparément, mais les styles de base sont obligatoires et les polices et tokens doivent être fournis ou explicitement remplacés.

Aksel utilise les couches CSS. Évitez les sélecteurs généraux hors couche, qui risquent de remplacer accidentellement les styles des composants. Les mises en page personnalisées de l’application doivent utiliser vos propres classes. L’aperçu autonome utilise des CSS locales et versionnées ainsi qu’une police délibérément remplacée ; l’exemple React présente un parcours d’intégration distinct, vérifié à partir des sources.

  1. Verrouillez ensemble les versions des paquets React et CSS.
  2. Importez la feuille de style une seule fois et utilisez les enfants sémantiques de Table pour le rendu.
  3. Gérez le tri et la sélection dans l’état de l’application.
  4. Vérifiez le changement de thème, les commandes au clavier et la zone de défilement étroite.

Consultez la spécification associée

Exemples de composants du système de design Aksel

Table React sémantique

Véritables enfants de Table et en-tête de ligne ; les quantités sont alignées à droite.

jsx
import { Table } from '@navikt/ds-react';
import '@navikt/ds-css';

export function CaseTable() {
  return <Table size="medium" zebraStripes>
    <caption>Fictional follow-up records</caption>
    <Table.Header><Table.Row>
      <Table.HeaderCell scope="col">Reference</Table.HeaderCell>
      <Table.HeaderCell scope="col">Next activity</Table.HeaderCell>
      <Table.HeaderCell scope="col" align="right">Waiting days</Table.HeaderCell>
    </Table.Row></Table.Header>
    <Table.Body><Table.Row>
      <Table.HeaderCell scope="row">DEMO-204</Table.HeaderCell>
      <Table.DataCell>Confirm appointment preference</Table.DataCell>
      <Table.DataCell align="right">4</Table.DataCell>
    </Table.Row></Table.Body>
  </Table>;
}

Référence du code

Syntaxe actuelle des primitives adaptatives

Utilisez les noms de tokens v8 dans les propriétés des primitives.

jsx
import { HStack, Box } from '@navikt/ds-react';
<HStack gap={{ xs: 'space-8', md: 'space-16' }}>
  <Box padding="space-16">First region</Box>
  <Box padding="space-16">Second region</Box>
</HStack>

Référence du code

Exemple autonome complet

Le document complet comprend sa mise en page, ses contrôles et son initialisation. Extrayez l’archive d’exemple liée pour obtenir les ressources de fournisseur avec leurs chemins relatifs exacts, puis servez le contenu via HTTP.

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>

Référence du code

  • Téléchargez l’exemple complet depuis les sources. Son fichier README indique la commande exacte pour le lancer localement.
  • Conservez des chemins relatifs pour les ressources de fournisseur par rapport à ce document ; l’archive contient toutes les ressources utilisées par cet aperçu.
04

Configuration de l’agent du système de design Aksel

Point de départ de l’implémentation

Le composant natif CSS 8.18.0 est rendu localement dans l’aperçu. La composition React a été vérifiée à partir des sources, mais n’a pas fait l’objet d’une compilation distincte. Alignez les versions ; ne combinez pas les classes navds v7 avec CSS v8. Le fichier ZIP d’exemple fonctionnel complet, disponible dans Sources, fournit également les dépendances exactes de l’aperçu et le document complet. Extrayez-le, exécutez python3 -m http.server 8080 dans ce répertoire, puis ouvrez http://localhost:8080/nav-aksel.html. N’ouvrez pas les exemples utilisant des modules avec file://.

bash
npm install @navikt/[email protected] @navikt/[email protected]
# React entry:
# import "@navikt/ds-css";
# import { Table, HStack, Box } from "@navikt/ds-react";

Un prompt pour votre projet

Prompt pour l’agent IA
Créez une table sémantique Aksel v8 avec les paquets CSS/React 8.18.0 correspondants. Conservez la légende, les en-têtes de colonnes et les en-têtes de lignes de référence. Utilisez les véritables tokens ax et les propriétés de primitives space-*. Prévoyez le tri numérique avec aria-sort, la sélection par cases à cocher fondée sur des identifiants stables et une case « tout sélectionner » à l’état indéterminé. Ne comptez pas sur onRowClick pour les interactions au clavier. Prenez en charge les tokens de rôle clair/sombre et une zone de défilement horizontal avec libellé sur les écrans étroits.
05

Sources et périmètre du système de design Aksel

Enregistrements d’exemple indépendants, sans identité NAV. La feuille de style native est utilisée avec une police de remplacement déclarée. Le tri, la sélection et la mise en page relèvent de l’application ; aucune donnée réelle sur les prestations ou les dossiers n’est présentée.