Государственные услуги и образование · Новый ресурс
Дизайн-система NL.
Создайте интерфейс для государственных услуг на основе реальных компонентов участников проекта и явно заданной темы. В этом примере Utrecht CSS показывает сопоставление токенов, структуру списка данных и две оригинальные темы с одинаковым процессом редактирования.
Встроенные компоненты кнопки и списка данных Utrecht CSS 9.0.15, исходные токены темы оформления и взаимодействие на уровне приложения. · Справочник по реализации
02
Дизайн-система NL Справочник по дизайну
Конкретный набор компонентов участника: @utrecht/component-library-css 9.0.15. Общедоступные имена токенов и классы — это API исследуемой библиотеки; числовые значения и цвета, помеченные как «пример», — исходные настройки приложения, а не универсальная спецификация NL Design System.
NL Design System прямо поддерживает объединение вклада нескольких организаций и позволяет описывать фирменный стиль каждой из них с помощью дизайн-токенов. Поэтому на практике интеграция состоит из выбора реализации компонента и темы. На этой странице выбрана реализация участника Utrecht CSS и оригинальная демонстрационная тема.
Этот выбор не означает, что Utrecht — каноническая реализация каждого компонента NL Design System. Он даёт читателю воспроизводимый пример, не требуя придумывать общенациональный шрифт, синий цвет или шкалу отступов. Фактически используется нативный пакет CSS @utrecht/component-library-css 9.0.15.
В заданной теме публичные пользовательские свойства --utrecht-* определены для обёртки. Кнопка использует эти значения, а её класс задаёт структуру компонента. Переменные с префиксом --_utrecht- — внутренние вычисления в изученной реализации CSS; их прямое изменение привяжет приложение к деталям реализации.
Бирюзовый #005a5b и фиолетовый #57328c в примере — оригинальные цвета приложения. Они демонстрируют возможность заменить фирменную палитру, не копируя стиль муниципалитета. Для текста на кнопках в обоих случаях используется белый цвет, а оттенок при наведении задан отдельно. Ни один цвет не обозначен как официальное значение токена NL Design System.
css
.example-theme {
/* Original application values, not a national house style. */
--utrecht-document-font-family: Arial, sans-serif;
--utrecht-button-font-size: 1rem;
--utrecht-button-line-height: 1.5;
--utrecht-button-font-weight: 700;
--utrecht-button-border-radius: .25rem;
--utrecht-button-min-block-size: 48px;
--utrecht-button-padding-block-start: .75rem;
--utrecht-button-padding-block-end: .75rem;
--utrecht-button-padding-inline-start: 1.25rem;
--utrecht-button-padding-inline-end: 1.25rem;
--utrecht-button-primary-action-background-color: #005a5b;
--utrecht-button-primary-action-color: #fff;
--utrecht-button-primary-action-hover-background-color: #003f40;
--utrecht-button-primary-action-hover-color: #fff;
--utrecht-focus-outline-color: #111;
--utrecht-focus-outline-width: 3px;
--utrecht-focus-outline-offset: 3px;
--utrecht-focus-outline-style: solid;
}
В демонстрации для чтения текста задан шрифт Arial, sans-serif размером 18px и межстрочный интервал 1.6. В первой теме заголовок размером 32px и скругление кнопки 4px; во второй — тот же удобный для чтения размер основного текста, скругление 8px и заголовок с засечками. Эти изменения тем намеренно хорошо заметны.
Если токен не задан, для нативной кнопки используется резервное минимальное значение block-size 44px. В нашей теме заданы 48px и явные значения внутренних блочных и строчных отступов. Это реальное значение API для CSS, выбранное приложением, а не предположительный размер для всей экосистемы. В примере также заданы максимальная ширина содержимого 56rem и промежутки 24px.
Для квитанции используется элемент dl с классом .utrecht-data-list и модификатором .utrecht-data-list--rows. Каждый .utrecht-data-list__item объединяет ключ dt и значение dd. Модификатор rows включает адаптивную сетку, промежутки между строками и границы; базовый класс списка данных без него такую компоновку не задаёт. Список HTML остаётся содержательным и до загрузки любой темы.
В квитанции указаны место получения, номер заявки и выбранный материал. Это не таблица с повторяющимися записями: каждый ключ обозначает отдельное свойство одного и того же запроса. На узких экранах ключ и значение располагаются друг под другом. Приложение задаёт токены строк, чтобы длинные названия мест помещались без обрезки.
Используйте dt для названия свойства, а dd — для его текущего значения.
Помещайте каждую пару ключ/значение в обёртку элемента, описанную в документации.
Разрешите перенос идентификаторов и длинных названий мест, чтобы они не расширяли страницу.
.utrecht-button задаёт базовый компонент, а .utrecht-button--primary-action выбирает группу токенов для основного оформления. Для локального действия, которое не должно отправлять окружающую форму, нативному элементу всё равно требуется атрибут type=button. Список данных доступен только для чтения, пока приложение не откроет панель редактирования.
Кнопка «Изменить место получения» в демонстрации открывает набор нативных переключателей radio в fieldset. При сохранении обновляется значение в списке определений, а новое место объявляется через область статуса с вежливым режимом оповещения. Отмена закрывает панель, не меняя сохранённое значение. Это поведение реализовано в коде приложения: одна лишь установка пакета CSS его не обеспечивает.
Переключатель темы меняет data-theme внешней обёртки. Классы компонентов, значения записи и выбранный переключатель radio остаются без изменений. Так на конкретном примере показано разделение white-label-оформления: одна и та же квитанция и логика взаимодействия могут использовать разные визуальные стили.
Здесь переключение темы — демонстрация для разработки, а не функция, которую обязана предлагать государственная служба. В реальном сервисе для нескольких организаций выбирайте тему из доверенной конфигурации приложения. Значения темы не должны влиять на право пользователя на услугу, проверку данных или смысл статуса.
Загрузите версионированные компоненты CSS один раз.
Примените соответствующие токены темы к содержащему элементу.
Отобразите в этой обёртке ту же разметку семантических компонентов.
Для каждой поддерживаемой темы проверьте фокус, переносы строк и цвета состояний.
Модель эстафеты NL Design System описывает, как отдельные вклады развиваются в направлении общих стандартов. Само наличие компонента в репозитории сообщества не гарантирует, что любое сочетание компонентов готово к использованию в рабочей среде. Сверьте выбранную реализацию, поддерживаемые состояния и текущую зрелость с документацией компонента.
В предварительном просмотре постоянно видна легенда вариантов места получения, сохранённый результат объявляется пользователю, а после редактирования фокус возвращается на инициировавшую его кнопку. Переключение темы не убирает фокус. Интерфейс остаётся доступным с нативным управлением radio с клавиатуры и собственными контурами фокуса приложения. Эти проверки дополняют тестирование компонента участника, но не заменяют его.
Установите дизайн-система NL и самостоятельно управляйте темой
Интеграция только с CSS
Установите проверенный пакет CSS и импортируйте dist/index.css с помощью сборщика, поддерживающего CSS, а затем подключите таблицу стилей темы. Для списка данных и кнопки CSS, используемых здесь, не требуется провайдер React или инициализатор компонента JavaScript. Исходный скрипт приложения управляет редактированием, сохранением, отменой и переключением тем.
Исходный код компонентов в комплекте распространяется по лицензии EUPL-1.2. При распространении сохраните уведомления об исходном коде и лицензии. Лицензия на код не означает разрешения использовать логотип муниципалитета. В этом примере использованы оригинальные темы, муниципальная символика отсутствует.
Полный документ включает разметку, элементы управления и инициализацию. Распакуйте связанный архив примера, чтобы получить нужные относительные пути к ресурсам поставщика, затем запустите его через HTTP-сервер.
html
<!doctype html><html lang="en"><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>NL Design System composition</title><link rel="stylesheet" href="vendor/utrecht-9.0.15/index.css"><style>.example-theme {
/* Original application values, not a national house style. */
--utrecht-document-font-family: Arial, sans-serif;
--utrecht-button-font-size: 1rem;
--utrecht-button-line-height: 1.5;
--utrecht-button-font-weight: 700;
--utrecht-button-border-radius: .25rem;
--utrecht-button-min-block-size: 48px;
--utrecht-button-padding-block-start: .75rem;
--utrecht-button-padding-block-end: .75rem;
--utrecht-button-padding-inline-start: 1.25rem;
--utrecht-button-padding-inline-end: 1.25rem;
--utrecht-button-primary-action-background-color: #005a5b;
--utrecht-button-primary-action-color: #fff;
--utrecht-button-primary-action-hover-background-color: #003f40;
--utrecht-button-primary-action-hover-color: #fff;
--utrecht-focus-outline-color: #111;
--utrecht-focus-outline-width: 3px;
--utrecht-focus-outline-offset: 3px;
--utrecht-focus-outline-style: solid;
}
*{box-sizing:border-box}body{margin:0}.example-theme{font:18px/1.6 Arial,sans-serif;color:#222;--accent:#005a5b;--wash:#eef6f4;--utrecht-data-list-rows-column-min-inline-size:12ch;--utrecht-data-list-rows-column-inline-size:45%;--utrecht-data-list-rows-gap:24px;--utrecht-data-list-rows-border-bottom-width:1px;--utrecht-data-list-rows-border-bottom-color:#ccd4d2;--utrecht-data-list-rows-item-padding-block-start:16px;--utrecht-data-list-rows-item-padding-block-end:16px;--utrecht-data-list-item-key-font-weight:700;--utrecht-data-list-item-value-line-height:1.6}.example-theme[data-theme=plum]{--accent:#57328c;--wash:#f5effa;--utrecht-button-primary-action-background-color:#57328c;--utrecht-button-primary-action-hover-background-color:#3c2262;--utrecht-button-border-radius:8px}.example-theme[data-theme=plum] h1{font-family:Georgia,serif}.toolbar{background:var(--wash);padding:20px 24px;border-bottom:4px solid var(--accent);display:flex;gap:16px;align-items:center;justify-content:space-between;flex-wrap:wrap}.toolbar label{font-size:16px}.toolbar select{font:inherit;max-width:100%;padding:8px}article{max-width:56rem;margin:auto;padding:32px 24px}h1{font-size:32px;line-height:1.3;margin:8px 0 24px}h2{font-size:24px}p{margin:16px 0}.utrecht-data-list__item-value{margin:0;overflow-wrap:anywhere}.utrecht-button{margin-block:8px}.editor{background:var(--wash);padding:24px;margin-block:24px}fieldset{border:0;padding:0;margin:0}legend{font-size:22px;font-weight:700;margin-bottom:16px}.choice{display:flex;align-items:center;gap:12px;padding:12px 0}.choice input{width:24px;height:24px;accent-color:var(--accent)}.buttons{display:flex;gap:24px;flex-wrap:wrap;align-items:center}.cancel{font:inherit;background:none;border:0;text-decoration:underline;min-height:48px;color:var(--accent);cursor:pointer}small{display:block;font-size:14px;margin-top:32px;color:#555}:focus-visible{outline:3px solid #111;outline-offset:3px}[hidden]{display:none!important}#notice{font-weight:700;color:var(--accent)}@media(max-width:600px){.example-theme{--utrecht-data-list-rows-column-min-inline-size:100%;}h1{font-size:28px}.toolbar{align-items:flex-start;flex-direction:column}.editor{padding:16px}}
</style><main class="example-theme" data-theme="teal"><div class="toolbar"><strong>Community collection · Example</strong><label>Original theme <select id="theme"><option value="teal">Teal</option><option value="plum">Plum</option></select></label></div><article><p>CONTRIBUTOR COMPONENTS + YOUR THEME</p><h1>Review your collection details</h1><p>This receipt uses Utrecht CSS components. Switching the theme changes public design tokens and preserves your choices.</p><dl class="utrecht-data-list utrecht-data-list--rows"><div class="utrecht-data-list__item"><dt class="utrecht-data-list__item-key">Item</dt><dd class="utrecht-data-list__item-value">Community reading pack</dd></div><div class="utrecht-data-list__item"><dt class="utrecht-data-list__item-key">Collection location</dt><dd class="utrecht-data-list__item-value" id="location">North library desk</dd></div><div class="utrecht-data-list__item"><dt class="utrecht-data-list__item-key">Reference</dt><dd class="utrecht-data-list__item-value">DEMO-2048</dd></div></dl><button id="edit" type="button" class="utrecht-button utrecht-button--primary-action">Change collection location</button><form class="editor" hidden><fieldset><legend>Choose a collection location</legend><label class="choice"><input type="radio" name="place" value="North library desk" checked>North library desk</label><label class="choice"><input type="radio" name="place" value="Riverside community room">Riverside community room</label><label class="choice"><input type="radio" name="place" value="Central welcome counter">Central welcome counter</label></fieldset><div class="buttons"><button class="utrecht-button utrecht-button--primary-action" type="submit">Save location</button><button type="button" class="cancel" id="cancel">Cancel</button></div></form><p id="notice" role="status"></p><small>Independent OpenDesign specimen. Utrecht CSS 9.0.15; original themes and fictional data. No municipal identity or external submission.</small></article></main><script>
const main=document.querySelector('main'),theme=document.querySelector('#theme'),edit=document.querySelector('#edit'),form=document.querySelector('form'),locationText=document.querySelector('#location'),notice=document.querySelector('#notice');let saved=locationText.textContent;theme.onchange=()=>main.dataset.theme=theme.value;edit.onclick=()=>{form.hidden=false;edit.hidden=true;notice.textContent='';[...form.elements.place].forEach(r=>r.checked=r.value===saved);form.querySelector(':checked').focus()};function close(){form.hidden=true;edit.hidden=false;edit.focus()}form.onsubmit=e=>{e.preventDefault();saved=form.elements.place.value;locationText.textContent=saved;notice.textContent='Collection location updated to '+saved+'.';close()};document.querySelector('#cancel').onclick=()=>{notice.textContent='No changes saved.';close()};
</script></html>
Скачайте полный пример из раздела «Источники». Точная команда локального запуска приведена в README.
Оставьте пути к ресурсам поставщика относительными к этому документу; архив включает все ресурсы, используемые в предварительном просмотре.
04
Настройка агента дизайн-система NL
Отправная точка для реализации
В автономном предварительном просмотре локально загружается та же версионированная нативная CSS. Для компонентов кнопки и списка данных, использующих только CSS, провайдер React не нужен. Вместе с библиотекой необходимо подключить оригинальные значения темы. ZIP-архив с полным рабочим примером в разделе источников содержит точные зависимости для предварительного просмотра и полный документ. Распакуйте архив, выполните в этой папке команду python3 -m http.server 8080 и откройте http://localhost:8080/nl-design-system.html. Не открывайте примеры на основе модулей через file://.
bash
npm install @utrecht/[email protected]
# CSS-aware application entry:
# import '@utrecht/component-library-css/dist/index.css';
# import './example-theme.css';
# Wrap the dl/button composition in <main class="example-theme">.
# Add application event handlers for editing and theme selection.
Запрос для вашего проекта
Промпт для AI-агента
Используйте @utrecht/component-library-css 9.0.15 для списка определений в квитанции и основной кнопки. Задайте оригинальную тему в области действия обёртки, используя публичные токены --utrecht-*, и не меняйте внутренние переменные --_utrecht-*. Реализуйте редактирование места получения с подписанными вариантами radio, сохранением и отменой, вежливым объявлением об изменении и возвратом фокуса. Покажите вторую оригинальную тему, не меняя разметку компонентов и не теряя данные. Укажите, что все числовые значения темы выбраны приложением.
05
Источники и область применения дизайн-система NL
NL Design System — независимая от брендов экосистема. В этом учебном примере выбрана реализация одного из участников и две оригинальные темы; он не претендует на общенациональный визуальный стиль и не использует идентификацию муниципалитета.