Государственные услуги · Новый ресурс

Дизайн-система Aksel.

Используйте реальные токены ax из Aksel v8, штатную плотность таблицы и семантическую структуру заголовков. Сортируйте и выбирайте вымышленные записи для последующей обработки, сравнивая светлую и тёмную темы.

Руководство OpenDesign8 глав13 записей ссылокАвторское руководство по приложению
01

Предварительный просмотр интерфейса дизайн-системы Aksel

Сортируйте записи по числу дней ожидания, выбирайте их, переключайте плотность и сравнивайте роли цветов в светлой и тёмной темах.

Рабочая панель для последующей обработкиОткрыть полный пример
Нативная таблица Aksel 8.18.0 CSS и токены с семантической разметкой HTML; локальная логика сортировки и выбора, явный резервный шрифт Arial. · Справочник по реализации
02

Проектная документация дизайн-системы Aksel

Проверены нативная таблица стилей @navikt/ds-css 8.18.0 и актуальная документация v8. Значения светлой и тёмной тем ограничены областью действия; предварительный просмотр заменяет удалённые шрифты на Arial и использует исходные демонстрационные записи.

Типографика v8

Источник
Название / правилоЗначение / конфигурацияПрименение
--ax-font-familySource Sans 3, Source Sans Pro, Arial, sans-serifВ предварительном просмотре явно задан резервный шрифт Arial.
--ax-font-weight-regular / bold400 / 600Не приравнивайте именованный жирный токен к значению 700.
--ax-font-size-medium / large1rem / 1.125rem16px / 18px при стандартном размере корневого шрифта.
--ax-font-size-heading-xlarge / 2xlarge2rem / 2.5rem32px / 40px.

Отступы и контрольные точки

Источник
Название / правилоЗначение / конфигурацияПрименение
--ax-space-8 / 16 / 24 / 320.5 / 1 / 1.5 / 2remНазвания токенов соответствуют стандартным значениям в пикселях.
--ax-radius-2 / 4 / 8 / 12 / 162 / 4 / 8 / 12 / 16pxРоли радиусов.
sm / md / lg / xl / 2xl480 / 768 / 1024 / 1280 / 1440pxЗначения проверены в версионированном CSS.

Геометрия нативной таблицы

Источник
Название / правилоЗначение / конфигурацияПрименение
Medium cell padding12px 8pxВертикальные / горизонтальные отступы по умолчанию.
Small / large vertical padding4px / 16pxМодификаторы плотности нативной таблицы; горизонтальный отступ остаётся равным 8px.
Header divider2pxРазделитель строк таблицы остаётся толщиной 1px.

Роли темы

Источник
Название / правилоЗначение / конфигурацияПрименение
--ax-bg-default#fff light / #0e151f darkКорневая поверхность.
--ax-text-neutral#202733 light / #dfe1e5 darkИтоговые значения neutral-1000.
--ax-bg-accent-strong#2176d4 light / #4580ca darkИтоговые значения accent-600; в коде используйте роль.
03

Полное руководство по дизайн-системе Aksel

Практическое руководство по выбору, применению и оценке этой системы для реального интерфейса.

DESIGN-nav-aksel.md

Подробные рекомендации, отправная точка для реализации и ссылки на источники.

Скачать руководство

Дизайн-система Aksel: начните с контракта v8

Не смешивайте старые классы с новыми токенами

В Aksel v8 используются токены --ax-* и классы компонентов .aksel. В руководстве по миграции указано, что старые классы .navds больше не работают, а токены для отдельных компонентов удалены. Поэтому обучающий материал на основе старого снимка экрана может выглядеть правдоподобно, но содержать неработающие рекомендации по реализации.

Из этого руководства OpenDesign

На этой странице зафиксирована нативная CSS версии 8.18.0 и приведена установка соответствующей React. В предварительном просмотре используются проверенные классы нативной таблицы и обычный HTML; приложение отвечает за JavaScript выбора и сортировки. Здесь не утверждается, что загрузка таблицы стилей создаёт экземпляр React Table.

Прочитать вспомогательную спецификацию

Дизайн-система Aksel: типографические роли и загрузка шрифтов

Для жирного токена используйте 600

В справочнике токенов в качестве стека шрифтов указаны Source Sans 3, Source Sans Pro, Arial и sans-serif. Обычное начертание соответствует 400, а именованный токен жирного начертания — 600. Размеры основного текста включают 14, 16, 18 и 20px; роли заголовков охватывают размеры до 24, 28, 32 и 40px.

В локальном предпросмотре в качестве шрифтового токена задан Arial, а унаследованное использование шрифтов явно переопределено, поэтому удалённые шрифты не загружаются. Это явно обозначенное решение для резервного шрифта, а не утверждение, что Arial — основной шрифт Aksel. Размеры текста компонентов по-прежнему задаёт CSS.

Прочитать вспомогательную спецификацию

Дизайн-система Aksel: отступы, радиусы и компоновка

Токены с размерами в пикселях преобразуются в rem

--ax-space-16 равен 1rem, а --ax-space-24 — 1.5rem. Синтаксис примитивов v8 соответствует этим именам: padding="space-16" и gap={{xs:"space-8",md:"space-16"}}. Не заменяйте их старым числовым свойством отступа, не проверив рекомендации по миграции.

В документации указаны следующие роли радиусов: 2, 4, 8, 12 и 16px, а также full. В предпросмотре сохранена исходная геометрия таблицы; для её элементов управления приложения используется space-24. Ширина области чтения 64rem выбрана локально, а значения контрольных точек взяты из изученной таблицы стилей.

Прочитать вспомогательную спецификацию

Дизайн-система Aksel: семантические цвета с учётом темы

Сохраняйте роль, а не отдельное значение hex

В исходной таблице стилей --ax-text-neutral соответствует neutral-1000: в светлой теме это #202733, а в тёмной — #dfe1e5. Значение --ax-bg-default меняется с белого на #0e151f. Если жёстко задать светлый цвет текста для тёмного контейнера, сопоставление ролей перестанет работать.

В предпросмотре переключается класс темы .light/.dark, а полосы таблицы, границы и цвета выбранных строк зависят от официальных токенов. У выбранной строки по-прежнему установлен флажок, и виден счётчик выбранных элементов. Одной окрашенной строки недостаточно для реализации выбора.

Прочитать вспомогательную спецификацию

Дизайн-система Aksel: семантическая структура таблицы

Заголовки — не обычные ячейки

В исходной таблице есть отдельные классы для заголовка, тела, строки, ячейки заголовка и ячейки данных. Эквивалент в React использует Table.Header, Table.Body, Table.Row, Table.HeaderCell и Table.DataCell. Столбец с идентификатором служит заголовком строки, а для каждого заголовка столбца задано scope=col.

Подпись задаёт название набора данных. Количество дней ожидания — числовое значение, поэтому оно выровнено по правому краю; идентификаторы остаются выровненными по левому. На узких экранах предпросмотр помещает горизонтальную прокрутку в подписанную область, доступную с клавиатуры, вместо того чтобы превращать строки в карточки и нарушать связи между элементами таблицы.

  • Используйте ячейки заголовков для названий столбцов и идентификаторов строк.
  • Выравнивайте по правому краю количественные значения, но не почтовые индексы и идентификаторы.
  • Добавьте подпись, чтобы у таблицы было понятное название.

Прочитать вспомогательную спецификацию

Дизайн-система Aksel: плотность и сортировка

Изменение плотности меняет отступы

В изученной исходной версии CSS для ячеек средней плотности используются space-12 по вертикали и space-8 по горизонтали. Для малой плотности по вертикали используется space-4, а для большой — space-16. Переключатель плотности меняет исходный класс модификатора; размер шрифта основного текста не уменьшается ради размещения большего количества информации на экране.

Заголовок Waiting days — кнопка сортировки в стиле исходного компонента. Её обработчик сортирует числовые значения и обновляет aria-sort у этого заголовка. Преобразование выполняет приложение: React API также предоставляет состояние сортировки и onSortChange, а не сортирует произвольные записи предметной области автоматически.

Прочитать вспомогательную спецификацию

Дизайн-система Aksel: выбор строк с поддержкой клавиатуры

Добавьте для каждой строки отдельный элемент управления

В документации Table отмечено, что одного onRowClick недостаточно для доступности с клавиатуры. Поэтому в примере для каждого идентификатора есть подписанный флажок, а также флажок для выбора всех строк. Если выбрана только часть строк, флажок общего выбора переходит в неопределённое состояние.

При сортировке выбранные строки определяются по стабильному идентификатору записи. Индекс строки в текущем порядке никогда не используется как ключ выбора: иначе при изменении порядка отметка перейдёт к другой записи. Счётчик выбранных элементов обновляется в области статуса с вежливым режимом объявления. Выбранные записи никуда не отправляются.

Прочитать вспомогательную спецификацию

Дизайн-система Aksel: подключение согласованных версий CSS и React

Используйте одинаковые версии пакетов

Установите @navikt/ds-react и @navikt/ds-css одной версии, затем один раз импортируйте CSS рядом с корнем приложения. Пакет уже содержит токены. Официальное руководство по импорту CSS также описывает подключение отдельных глобальных файлов и файлов компонентов, но базовый набор обязателен; шрифты и токены нужно подключить либо явно заменить.

В Aksel используются слои CSS. Избегайте широких селекторов вне слоёв: они могут непреднамеренно переопределить стили компонентов. Собственную компоновку приложения задавайте своими классами. В автономном предпросмотре используются локальные версии CSS и намеренно заменённый шрифт; пример React — отдельный вариант интеграции, проверенный по исходному коду.

  1. Закрепите одинаковые версии пакетов React и CSS.
  2. Импортируйте таблицу стилей один раз и используйте семантические дочерние элементы Table.
  3. Храните сортировку и выбор в состоянии приложения.
  4. Проверьте переключение темы, управление с клавиатуры и область прокрутки на узком экране.

Прочитать вспомогательную спецификацию

Примеры компонентов дизайн-системы Aksel

Семантическая таблица React Table

Настоящие дочерние элементы Table и заголовок строки; количественные значения выровнены по правому краю.

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

Справочник по коду

Актуальный синтаксис адаптивных примитивов

Используйте имена токенов v8 в свойствах примитивов.

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>

Справочник по коду

Полный автономный пример

Полный документ включает разметку, элементы управления и инициализацию. Распакуйте связанный архив примера, чтобы получить нужные относительные пути к ресурсам поставщика, затем запустите его через 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>

Справочник по коду

  • Скачайте полный пример из раздела «Источники». Точная команда локального запуска приведена в README.
  • Оставьте пути к ресурсам поставщика относительными к этому документу; архив включает все ресурсы, используемые в предварительном просмотре.
04

Настройка агента дизайн-системы Aksel

Отправная точка для реализации

В предпросмотре локально отрисовывается исходный CSS 8.18.0. Композиция React проверена по исходному коду, но отдельно не собиралась. Используйте согласованные версии; не сочетайте классы navds из v7 с CSS v8. ZIP-архив с полностью рабочим примером в разделе Sources также содержит точные зависимости предпросмотра и полный документ. Распакуйте его, выполните python3 -m http.server 8080 в этой директории, затем откройте http://localhost:8080/nav-aksel.html. Не открывайте примеры на основе модулей через file://.

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

Запрос для вашего проекта

Промпт для AI-агента
Создайте семантическую таблицу Aksel v8, используя согласованные пакеты CSS/React версии 8.18.0. Добавьте подпись, заголовки столбцов и заголовки строк с идентификаторами. Используйте настоящие токены ax и свойства примитивов space-*. Реализуйте сортировку числовых значений с aria-sort, выбор флажками по стабильному идентификатору и общий выбор с неопределённым состоянием флажка. Не полагайтесь на onRowClick для взаимодействия с клавиатуры. Поддержите ролевые токены светлой и тёмной тем и подписанную область горизонтальной прокрутки на узких экранах.
05

Дизайн-система Aksel: источники и область применения

Самостоятельные примеры записей без идентификации NAV. Используется исходная таблица стилей с явно указанным резервным шрифтом. Сортировка, выбор и компоновка реализованы на уровне приложения; реальные данные о преимуществах или практических случаях не приводятся.