Administración pública y servicios públicos · Nuevo recurso

Sistema de diseño Aksel.

Usa los tokens ax reales de Aksel v8, la densidad de tabla nativa y una estructura semántica para los encabezados. Ordena y selecciona registros ficticios de seguimiento mientras comparas los temas claro y oscuro.

Guía de OpenDesign8 capítulos13 entradas de referenciaGuía de aplicación original
01

Vista previa de la interfaz del sistema de diseño Aksel

Ordena los días de espera por valor numérico, selecciona registros, cambia la densidad y compara los roles de los temas claro y oscuro.

Espacio de trabajo para tablas de seguimientoAbrir ejemplo completo
Tabla nativa de Aksel 8.18.0, CSS y tokens con HTML semántico; código local para ordenación y selección, y alternativa explícita Arial. · Referencia de implementación
02

Referencia de diseño del sistema de diseño Aksel

@navikt/ds-css 8.18.0: se inspeccionaron la hoja de estilos nativa y la documentación actual de v8. Los valores para los temas claro y oscuro están delimitados por ámbito; la vista previa sustituye las fuentes remotas por Arial y utiliza los registros originales del ejemplo.

Tipografía de v8

Fuente
Nombre / ReglaValor / ConfiguraciónUso
--ax-font-familySource Sans 3, Source Sans Pro, Arial, sans-serifLa vista previa usa explícitamente Arial como fuente alternativa.
--ax-font-weight-regular / bold400 / 600No equipares el token de negrita con 700.
--ax-font-size-medium / large1rem / 1.125rem16px / 18px con el tamaño raíz estándar.
--ax-font-size-heading-xlarge / 2xlarge2rem / 2.5rem32px / 40px.

Espaciado y puntos de ruptura

Fuente
Nombre / ReglaValor / ConfiguraciónUso
--ax-space-8 / 16 / 24 / 320.5 / 1 / 1.5 / 2remLos nombres de los tokens indican sus equivalencias estándar en píxeles.
--ax-radius-2 / 4 / 8 / 12 / 162 / 4 / 8 / 12 / 16pxRoles de radio de borde.
sm / md / lg / xl / 2xl480 / 768 / 1024 / 1280 / 1440pxValores inspeccionados en la versión CSS.

Geometría de la tabla nativa

Fuente
Nombre / ReglaValor / ConfiguraciónUso
Medium cell padding12px 8pxRelleno vertical / horizontal predeterminado.
Small / large vertical padding4px / 16pxModificadores de densidad nativos; el relleno horizontal se mantiene en 8px.
Header divider2pxEl separador de las filas del cuerpo sigue siendo de 1px.

Roles del tema

Fuente
Nombre / ReglaValor / ConfiguraciónUso
--ax-bg-default#fff light / #0e151f darkSuperficie raíz.
--ax-text-neutral#202733 light / #dfe1e5 darkValores resueltos de neutral-1000.
--ax-bg-accent-strong#2176d4 light / #4580ca darkValores resueltos de accent-600; usa el rol en el código.
03

Guía completa del sistema de diseño de Aksel

Una guía práctica para elegir, aplicar y revisar este sistema en una interfaz real.

DESIGN-nav-aksel.md

Orientación completa, un punto de partida para la implementación y enlaces al código fuente.

Descargar la guía

Empieza con el contrato de v8 del sistema de diseño de Aksel

No mezcles clases antiguas con tokens nuevos

v8 de Aksel usa tokens --ax-* y clases de componentes .aksel. La guía de migración indica que las clases antiguas .navds ya no funcionan y que se han eliminado los tokens específicos de los componentes. Por eso, un tutorial basado en una captura antigua puede parecer correcto y, aun así, dar indicaciones de implementación que no funcionan.

De esta guía de OpenDesign

Esta página fija CSS nativo en 8.18.0 y proporciona la instalación correspondiente de React. La vista previa utiliza clases de tabla nativas inspeccionadas con HTML estándar; la aplicación JavaScript gestiona la selección y la ordenación. No afirma que descargar una hoja de estilos instancie una tabla de React.

Consulta la especificación complementaria

Roles tipográficos y carga de fuentes del sistema de diseño de Aksel

Usa 600 para el token de negrita

La referencia de tokens define la pila de fuentes Source Sans 3, Source Sans Pro, Arial y sans-serif. El estilo normal corresponde a 400 y el token denominado negrita, a 600. Los tamaños del cuerpo incluyen 14, 16, 18 y 20px; los roles de encabezado llegan a 24, 28, 32 y 40px.

La vista previa local asigna Arial al token de fuente y anula explícitamente el uso heredado de fuentes, por lo que no realiza solicitudes de fuentes remotas. Es una decisión de fuente alternativa declarada, no una afirmación de que Arial sea la tipografía principal del sistema de diseño Aksel. CSS sigue proporcionando el tamaño del texto de los componentes.

Consulta la especificación complementaria

Espaciado, radio y diseño del sistema de diseño de Aksel

Los tokens con nombres en píxeles se resuelven en rem

--ax-space-16 equivale a 1rem y --ax-space-24, a 1.5rem. La sintaxis de primitivas de v8 sigue esos nombres: padding="space-16" y gap={{xs:"space-8",md:"space-16"}}. No se sustituye una propiedad de espaciado numérica antigua sin consultar la guía de migración.

Los roles de radio documentados incluyen 2, 4, 8, 12 y 16px, además de full. La vista previa conserva la geometría de la tabla nativa y usa space-24 alrededor de los controles de la aplicación. El ancho de lectura de 64rem es una elección local; los valores de los puntos de ruptura proceden de la hoja de estilos inspeccionada.

Consulta la especificación complementaria

Colores semánticos adaptados al tema del sistema de diseño de Aksel

Conserva el rol, no un único valor hexadecimal

La hoja de estilos nativa resuelve --ax-text-neutral como neutral-1000: #202733 en el tema claro y #dfe1e5 en el oscuro. --ax-bg-default cambia de blanco a #0e151f. Fijar el valor claro del texto en un contenedor oscuro anularía la correspondencia de roles.

La vista previa cambia la clase del tema .light/.dark y permite que los colores de las franjas, los bordes y las filas seleccionadas de la tabla sigan los tokens oficiales. La selección se indica mediante una casilla marcada y un contador visible. Una fila coloreada, por sí sola, no constituye una interfaz de selección.

Consulta la especificación complementaria

Anatomía semántica de las tablas del sistema de diseño de Aksel

Los encabezados no son celdas comunes

La tabla nativa tiene clases distintas para el encabezado, el cuerpo, las filas, las celdas de encabezado y las celdas de datos. El equivalente de React usa Table.Header, Table.Body, Table.Row, Table.HeaderCell y Table.DataCell. La columna de referencia es un encabezado de fila y cada encabezado de columna tiene scope=col.

El título describe la colección. Los días de espera son cantidades y se alinean a la derecha; los identificadores de referencia se mantienen alineados a la izquierda. En anchos reducidos, la vista previa conserva el desplazamiento horizontal dentro de una región con etiqueta y foco de teclado, en lugar de destruir las relaciones de la tabla para convertir las filas en tarjetas.

  • Usa celdas de encabezado tanto para las etiquetas de columna como para los identificadores de fila.
  • Alinea a la derecha los valores cuantitativos, no los códigos postales ni los identificadores.
  • Añade un título para que la tabla tenga un nombre descriptivo.

Consulta la especificación complementaria

Densidad y ordenación del sistema de diseño de Aksel

Al cambiar la densidad, cambia el relleno

En el CSS nativo inspeccionado, las celdas de densidad media usan space-12 en vertical y space-8 en horizontal. La densidad pequeña usa space-4 en vertical y la grande, space-16. El selector de densidad cambia la clase modificadora nativa; no reduce el tamaño de fuente del cuerpo para forzar que quepa más información en la ventana gráfica.

El encabezado Waiting days es un botón de ordenación de estilo nativo. Su controlador ordena los valores numéricos y actualiza aria-sort en ese encabezado. La aplicación gestiona esta transformación: API de React también expone el estado de ordenación y onSortChange, en lugar de ordenar automáticamente registros arbitrarios del dominio.

Consulta la especificación complementaria

Selección de filas segura con el teclado en el sistema de diseño de Aksel

Proporciona un control explícito para cada fila

La documentación de Table advierte que onRowClick por sí solo no es accesible con el teclado. Por eso, el ejemplo incluye una casilla etiquetada para cada referencia y otra para seleccionar todas. La casilla general pasa al estado indeterminado cuando solo se seleccionan algunas filas.

La ordenación conserva la selección mediante el identificador de referencia estable. Nunca usa el índice actual de la fila como clave de selección, ya que el cambio de orden marcaría otro registro. El contador de selección se actualiza en una región de estado cortés. No se envían registros seleccionados a ningún sitio.

Consulta la especificación complementaria

Carga CSS y React compatibles con sistema de diseño Aksel

Mantén sincronizadas las versiones de los paquetes

Instala @navikt/ds-react y @navikt/ds-css en la misma versión e importa CSS una sola vez, cerca de la raíz de la aplicación. El paquete ya incluye los tokens. La guía oficial de importación de CSS también admite archivos globales y de componentes de forma granular, pero se requiere la configuración base y las fuentes y los tokens deben proporcionarse o sustituirse explícitamente.

Aksel utiliza capas de CSS. Evita selectores generales fuera de capa que anulen accidentalmente los estilos de los componentes. El diseño personalizado de la aplicación debe aplicarse a tus propias clases. La vista previa independiente incluye CSS local con versiones fijadas y una fuente sustituida deliberadamente; el ejemplo de React es una vía de integración distinta y verificada en el código fuente.

  1. Fija las versiones de los paquetes React y CSS conjuntamente.
  2. Importa la hoja de estilos una sola vez y renderiza los elementos secundarios semánticos de Table.
  3. Mantén la ordenación y la selección en el estado de la aplicación.
  4. Comprueba el cambio de tema, los controles de teclado y la región de desplazamiento estrecha.

Consulta la especificación complementaria

Ejemplos de componentes del sistema de diseño de Aksel

Tabla semántica de React

Elementos hijos reales de Table y un encabezado de fila; las cantidades se alinean a la derecha.

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>;
}

Referencia de código

Sintaxis actual de primitivos adaptables

Usa los nombres de tokens de v8 en las propiedades de los primitivos.

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>

Referencia de código

Ejemplo independiente completo

El documento completo incluye su estructura, controles e inicialización. Extrae el archivo de ejemplo enlazado para obtener los recursos del proveedor con sus rutas relativas exactas y luego sírvelo mediante 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>

Referencia de código

  • Descarga el ejemplo completo desde Fuentes. El README contiene el comando exacto para ejecutarlo en local.
  • Mantén las rutas de los recursos del proveedor relativas a este documento; el archivo incluye todos los recursos que utiliza esta vista previa.
04

Configuración del agente del sistema de diseño de Aksel

Punto de partida para la implementación

CSS 8.18.0 nativo se representa localmente en la vista previa. La composición de React se ha verificado en el código fuente, pero no se ha compilado por separado. Mantén las versiones alineadas; no combines las clases navds de v7 con CSS de v8. El ZIP del ejemplo funcional completo en Sources también incluye las dependencias exactas de la vista previa y el documento completo. Descomprímelo, ejecuta python3 -m http.server 8080 en ese directorio y abre http://localhost:8080/nav-aksel.html. No abras ejemplos basados en módulos mediante file://.

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

Una instrucción para tu proyecto

Instrucción para el agente
Crea una tabla semántica de Aksel v8 con paquetes CSS/React 8.18.0 compatibles. Mantén el título, los encabezados de columna y los encabezados de fila de referencia. Usa tokens ax reales y las propiedades de primitivos space-*. Incluye ordenación numérica con aria-sort, selección de casillas con identificadores estables y selección de todo con estado indeterminado. No dependas de onRowClick para la interacción con el teclado. Admite tokens de rol claros y oscuros, y una región de desplazamiento horizontal con etiqueta en pantallas estrechas.
05

Fuentes y alcance del sistema de diseño de Aksel

Registros de ejemplo independientes, sin identidad de NAV. Se usa la hoja de estilos nativa y se indica la fuente alternativa. La ordenación, la selección y la disposición son comportamientos de la aplicación; no se muestran datos reales de beneficios ni de casos.