Ariakit предоставляет неоформленные компоненты React с явно заданным общим состоянием и доступными составными элементами. Компонент combobox отделяет ввод текста от подтверждённого выбора, поэтому подходит для средств выбора с поиском; расположенный ниже справочник демонстрирует эту разницу на сгруппированных и недоступных результатах.
Руководство OpenDesign9 глав29 справочных материаловАвторское руководство по приложению
01
Дизайн-система Ariakit Предпросмотр интерфейса
Фильтруйте справочные материалы по группам, выбирайте с помощью клавиш «Стрелка вниз» и «Enter», просматривайте результат и добавляйте его в локальный список для чтения.
Нативные @ariakit/react 0.4.40 и React 19. Все визуальные токены и примеры справочных материалов созданы специально. · Справочник по реализации
02
Ariakit Справочник по дизайн-системе
Ariakit React 0.4.40 — это неоформленный инструментарий для обеспечения доступности. Он не предоставляет приведённую ниже палитру страницы, шкалу размеров шрифта или интервалы в качестве встроенной темы дизайна. Все значения --app-* — явно заданная оригинальная конфигурация этого работающего примера; названия компонентов и атрибуты состояния — API Ariakit.
Дизайн-система Ariakit: начните с модели состояния Combobox
Начните с модели состояний Combobox
ComboboxProvider в Ariakit связывает подпись, редактируемое поле ввода, кнопку раскрытия, всплывающее окно и варианты. Провайдер управляет общим состоянием взаимодействия, а каждый компонент отвечает за свою часть структуры. Благодаря этому поле поиска и панель сведений о выбранном элементе можно расположить независимо друг от друга, не превращая каждое нажатие клавиши в новый выбор.
В демонстрации поиска по справочнику представлены шесть записей в двух именованных группах. Фильтрация выполняется на уровне коллекции приложения, а навигация и выбор варианта — встроенным компонентом Combobox. Чёткое разделение этих задач особенно полезно при замене статических записей другим источником данных: отфильтрованный набор результатов и текущий зафиксированный элемент — не обязательно одно и то же.
Дизайн-система Ariakit: поисковый текст и зафиксированный выбор — разные состояния
Текст поиска и подтверждённый выбор — разные состояния
В примере inputValue и setInputValue управляют вводимым текстом, а selectedValue и setSelectedValue — выбранной записью справочника. В проверенной версии API 0.4.40 inputValue — актуальное название состояния поля ввода; в старых примерах могут встречаться устаревшие псевдонимы value/setValue. В полном примере используются актуальные названия.
Ввод слова «color» сокращает список вариантов, но сразу не меняет отображаемую карточку сведений. Выбор пункта «Роли цветов» фиксирует его и обновляет панель. Очистка поискового запроса также не сбрасывает последний выбранный справочник. Если считать каждый неполный запрос зафиксированным значением, в панели сведений будут появляться недопустимые или несуществующие записи.
Дизайн-система Ariakit: свяжите подпись, поле ввода, кнопку раскрытия и всплывающее окно
Свяжите метку, поле ввода, раскрывающий элемент и всплывающую панель
ComboboxProvider предоставляет общее состояние компонентам ComboboxLabel, Combobox, ComboboxDisclosure и ComboboxPopover. Видимая подпись обозначает поле ввода. Кнопка раскрытия — отдельная кнопка с явным доступным именем, а всплывающее окно с параметром sameWidth и отступом в восемь пикселей сохраняет выравнивание относительно привязанного элемента.
Каждый результат — это ComboboxItem со стабильным значением. Разделы «Основы» и «Компоненты» реализованы как встроенные группы ComboboxGroup с заголовками ComboboxGroupLabel. Заголовок, лишь визуально выделенный жирным в неструктурированном списке, не выражает ту же связь группировки: встроенная структура задаёт её вместе с моделью клавиатурной навигации.
Дизайн-система Ariakit: отфильтруйте данные перед отображением встроенных вариантов
Фильтруйте данные до отрисовки нативных элементов
В коллекции примера — пять доступных справочных материалов и одна намеренно недоступная сетка «Экспериментальная». Фильтрация на уровне приложения выполняется без учёта регистра: для каждого названия ищется подстрока. Группы отображаются, только если в них есть подходящие записи, поэтому между результатами не остаются пустые заголовки.
Если по запросу ничего не найдено, показывается отдельное сообщение с предложением очистить поиск или попробовать запрос «color». Это сообщение не становится выбираемым вариантом. Недоступная запись, если она соответствует запросу, остаётся видимой с пометкой «Недоступно», а встроенное свойство disabled не позволяет зафиксировать её как выбранную.
Дизайн-система Ariakit: проверьте реальную последовательность Down и Enter
Проверьте реальную последовательность клавиш «Стрелка вниз» и «Enter»
В примере параметр autoSelect отключён. После ввода запроса клавиша Down переводит к списку вариантов, а Enter выбирает активный пункт. Escape закрывает всплывающее окно. Это соответствует видимым инструкциям; проверка учитывала заголовок сведений о выбранном элементе, а не только появление раскрывающегося списка.
В другом продукте может быть уместно автоматически выделять вариант, но это меняет исходную позицию клавиатурной навигации по стрелкам. Если сразу активен единственный результат, следующее нажатие Down может вернуть фокус в поле ввода. В примере такого несоответствия нет: активный вариант оформляется через data-active-item, а его положение в клавиатурной навигации не смешивается с наличием записи в сохранённом списке для чтения.
Введите «color» и дождитесь подходящего варианта.
Нажмите Down, затем Enter и проверьте панель сведений «Роли цветов».
Введите название недоступного или несуществующего справочного материала и убедитесь, что непреднамеренный выбор не зафиксирован.
Дизайн-система Ariakit: для активного варианта, кольца фокуса и сохранённого состояния нужны разные обозначения
Для активного варианта, рамки фокуса и сохранённого состояния нужны разные визуальные сигналы
У поля ввода и кнопки раскрытия видимые контуры фокуса. Активный вариант выделяется светло-зелёным фоном и внутренним контуром толщиной в один пиксель, заданными встроенным атрибутом data-active-item. Для недоступных вариантов снижается визуальный акцент и сохраняется явная текстовая пометка. Эти стили не полагаются только на наведение указателя.
После добавления выбранного справочного материала в список для чтения кнопка Add становится недоступной, а её текст меняется. Это состояние сохранения принадлежит приложению и не связано с текущим активным результатом Combobox. Светло-зелёный фон сохранённого действия помогает не воспринимать недоступное действие как ещё одну активную основную кнопку.
Дизайн-система Ariakit: список для чтения не заменяет текущий справочный материал
Список для чтения не заменяет текущий справочник
При добавлении справочный материал помещается в локальный массив; повторно одно и то же название не добавляется. Текущий материал остаётся на экране, чтобы пользователь мог изучить его примечания. У каждой строки списка для чтения есть отдельная кнопка Remove с понятным назначением. После удаления записи кнопка Add снова становится доступной, если этот материал всё ещё выбран. Количество элементов вычисляется по длине массива.
В демонстрационные сведения включены рекомендации по типографике, интервалам и компонентам, чтобы исследовать справочник было полезно. Их значения явно обозначены как оригинальное содержимое примера. Запись «Размер дисплея — 36px» в шкале типографики нельзя принимать за токен типографики Ariakit: Ariakit не предоставляет эту систему дизайна.
Дизайн-система Ariakit: всплывающему окну нужно место, но оно не должно менять размер всей страницы
Всплывающему окну нужно место, но оно не должно менять размер всей страницы
Ширина всплывающего окна соответствует ширине поля ввода, а его высота ограничена 340px. Если результатов больше, список прокручивается внутри этой области, а карточка сведений о выбранном элементе остаётся обычным содержимым документа. Сохраняйте связь между полем ввода, кнопкой раскрытия и списком вариантов, даже если карточка сведений переместится в другую колонку: выбор элемента по-прежнему должен обновлять ту же выбранную запись.
На исходной контрольной ширине 700px поле поиска и карточка сведений располагаются друг под другом. Элементы управления поиском, подсказка по клавиатуре и список для чтения остаются перед карточкой выбранного элемента в порядке документа. Декоративная иллюстрация справочного материала скрыта от вспомогательных технологий, поскольку смысл передают заголовок и примечания.
Ограничьте длинный список вариантов отдельной прокручиваемой областью, сохранив удобные интервалы между элементами.
Оставьте панель зафиксированных сведений за пределами временного всплывающего окна.
Сохраняйте видимые подписи полей ввода и подсказки по клавиатуре на мобильных устройствах.
Дизайн-система Ariakit: свяжите провайдер, коллекцию и таблицу стилей
Свяжите провайдер, коллекцию и таблицу стилей
Установите @ariakit/react 0.4.40 в проект React и сохраните полную композицию провайдера и компонентов из App.jsx. В текущем примере используются отдельные управляемые пары inputValue/setInputValue и selectedValue/setSelectedValue. Сохраняйте выбранную запись, даже если текущий поисковый запрос скрывает её из всплывающего списка.
Подключите style.css к компоненту. Правило data-active-item в этом файле соответствует позиции Combobox в клавиатурной навигации, а стили сохранённого списка — состоянию приложения. При замене результатов на загружаемые асинхронно сохраняйте оба канала состояния и связи между группами и вариантами; не подменяйте панель зафиксированных сведений промежуточной строкой поискового запроса.
Провайдер, подпись, поле ввода, кнопка раскрытия, сгруппированные варианты всплывающего списка и действия локального списка для чтения.
jsx
import React,{useState} from 'react';
import * as Ariakit from '@ariakit/react';
const resources=[{name:'Type scale',group:'Foundations',code:'Aa',description:'A compact editorial hierarchy for headings, supporting text and labels.',notes:['Display · 36px / 1.1','Section · 24px / 1.25','Body · 16px / 1.6'],color:'#f0dbc3'},{name:'Color roles',group:'Foundations',code:'◐',description:'Separate surface, text, boundary and action roles before naming brand colors.',notes:['Canvas and raised surface','Primary and muted text','Action and on-action pair'],color:'#d6e5d8'},{name:'Spacing rhythm',group:'Foundations',code:'▥',description:'Use a small set of intervals to show relationships between content groups.',notes:['8px within a compact group','16px between related controls','32px between sections'],color:'#d6dfee'},{name:'Form field',group:'Components',code:'⌑',description:'Keep the label, hint, input and error message in one understandable group.',notes:['Persistent visible label','Hint before an error exists','Error connected to the input'],color:'#e9d8de'},{name:'Navigation menu',group:'Components',code:'☷',description:'A small set of destinations with a visible current location and keyboard access.',notes:['Destination labels describe content','Current item has a text/state cue','Collapsed layout keeps names'],color:'#e7e0c5'},{name:'Experimental grid',group:'Components',code:'▦',description:'Unavailable in this sample collection.',notes:[],color:'#e3e3e3',disabled:true}];
export default function App(){const[query,setQuery]=useState(''),[chosen,setChosen]=useState('Type scale'),[saved,setSaved]=useState([]);const selected=resources.find(x=>x.name===chosen)||resources[0],matches=resources.filter(x=>x.name.toLowerCase().includes(query.toLowerCase()));return <main className="resource-finder"><header><p className="eyebrow">ARIAKIT · ACCESSIBLE PRIMITIVES</p><h1>A reference, within reach.</h1><p>Search a small collection with the keyboard, inspect the result and keep a local reading list.</p></header><div className="finder-grid"><section className="search-area"><Ariakit.ComboboxProvider inputValue={query} setInputValue={setQuery} selectedValue={chosen} setSelectedValue={setChosen}><Ariakit.ComboboxLabel className="label">Find a reference</Ariakit.ComboboxLabel><div className="input-row"><Ariakit.Combobox className="combobox" placeholder="Try type, color or form" /><Ariakit.ComboboxDisclosure className="disclosure" aria-label="Show reference suggestions">⌄</Ariakit.ComboboxDisclosure></div><Ariakit.ComboboxPopover gutter={8} sameWidth className="popover">{['Foundations','Components'].map(group=>{const items=matches.filter(x=>x.group===group);return items.length?<Ariakit.ComboboxGroup key={group}><Ariakit.ComboboxGroupLabel className="group-label">{group}</Ariakit.ComboboxGroupLabel>{items.map(x=><Ariakit.ComboboxItem key={x.name} value={x.name} disabled={x.disabled} className="combo-item"><span>{x.name}</span><small>{x.disabled?'Unavailable':x.group==='Foundations'?'Guide':'Pattern'}</small></Ariakit.ComboboxItem>)}</Ariakit.ComboboxGroup>:null})}{!matches.length&&<p className="empty" role="status">No matching reference. Try “color” or clear the search.</p>}</Ariakit.ComboboxPopover></Ariakit.ComboboxProvider><p className="hint">Type to filter. Use ↓ and ↑ to browse, Enter to choose, Escape to close.</p><div className="collection-note"><span>06</span><div><strong>Sample references</strong><p>Five available, one deliberately disabled to show an unavailable item.</p></div></div><section className="reading-list"><h2>Your reading list <small>{saved.length}</small></h2>{saved.length?<ul>{saved.map(name=><li key={name}><span>{name}</span><Ariakit.Button className="remove" onClick={()=>setSaved(saved.filter(x=>x!==name))} aria-label={`Remove ${name}`}>Remove</Ariakit.Button></li>)}</ul>:<p className="muted">Choose a reference, then add it here.</p>}<p className="local-note">This list stays in memory and clears on reload.</p></section></section><section className="reference-card" aria-label="Selected reference"><div className="reference-art" style={{background:selected.color}} aria-hidden="true"><span>{selected.code}</span><i></i></div><div className="reference-body"><p className="eyebrow">{selected.group} · SAMPLE CONTENT</p><h2>{selected.name}</h2><p>{selected.description}</p><ul className="note-list">{selected.notes.map(note=><li key={note}>{note}</li>)}</ul><Ariakit.Button className="primary" disabled={saved.includes(selected.name)} onClick={()=>setSaved([...saved,selected.name])}>{saved.includes(selected.name)?'Added to reading list':'Add to reading list'}</Ariakit.Button><p className="scope-note">These sample reference values are original content, not Ariakit design tokens.</p></div></section></div><p className="selection-status" role="status">Selected reference: {selected.name}</p></main>}
Ariakit предоставляет поведение и семантику, а не эту систему цветов и интервалов.
Активный результат оформляется с помощью data-active-item.
Для всплывающего окна заданы собственные максимальная высота и область прокрутки.
04
Настройка агента дизайн-системы Ariakit
Отправная точка для реализации
Проверено с @ariakit/react 0.4.40 и React 19. Используются актуальные имена inputValue/setInputValue и управляемый selectedValue.
jsx
// Create the project first:
// npm create vite@latest ariakit-specimen -- --template react
// cd ariakit-specimen && npm install
// In a Vite React project:
// npm install @ariakit/[email protected] react@19 react-dom@19
// Save the complete component as App.jsx and the visual configuration as style.css.
import React from 'react';
import {createRoot} from 'react-dom/client';
import App from './App.jsx';
import './style.css';
createRoot(document.getElementById('root')).render(<App />);
// index.html contains <div id="root"></div>.
// No Ariakit theme stylesheet is required; style.css is this example's original theme.
// Keep the template index.html and replace its entry with the code above.
// npm run dev
Запрос для вашего проекта
Промпт для AI-агента
Используйте предоставленный эталонный поиск по справочнику Ariakit 0.4.40 в React. Храните inputValue/setInputValue из ComboboxProvider отдельно от selectedValue/setSelectedValue, оставьте группы с нативной семантической разметкой и отключённый пункт Experimental grid, а данные фильтруйте до отображения элементов. Сохраните проверенный сценарий: Down, затем Enter при выключенном autoSelect; оформляйте data-active-item отдельно от состояния сохранения. Добавляйте сохранённый справочный материал в локальный список для чтения без дубликатов и разрешите удалять его, не закрывая текущую карточку. Включите исходную таблицу стилей целиком.
05
Источники и область действия дизайн-системы Ariakit
Ariakit React 0.4.40. Все визуальные токены, иллюстрации и примеры значений — оригинальные настройки; они не претендуют на соответствие официальной палитре или шкале типографики Ariakit. Состояние списка для чтения хранится локально.