bukatchuk ui

Элементы

Поле с поиском

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

combobox с версии 0.1.0 со скриптом

Примеры

Часовой пояс встречи

Время встреч в приглашениях показывается в этом поясе.

<form action="#" method="post">
  <div class="field">
    <label class="field__label" for="cb-tz">Часовой пояс</label>
    <div class="combo" data-ui-combobox>
      <input class="field__input combo__input" type="text" id="cb-tz" role="combobox" aria-expanded="false" aria-controls="cb-tz-list" aria-autocomplete="list" autocomplete="off" placeholder="Начните вводить город" value="Москва">
      <input type="hidden" name="timezone" value="Europe/Moscow">
      <button class="combo__toggle" type="button" tabindex="-1" aria-label="Показать все варианты" aria-expanded="false" aria-controls="cb-tz-list">▾</button>
      <div class="combo__pop" hidden>
        <ul class="combo__list" id="cb-tz-list" role="listbox" aria-label="Часовые пояса">
          <li class="combo__option" role="option" data-value="Europe/Kaliningrad" data-ui-search="UTC+2">Калининград <small>UTC+2</small></li>
          <li class="combo__option" role="option" data-value="Europe/Moscow" data-ui-search="UTC+3" aria-selected="true" data-ui-default>Москва <small>UTC+3</small></li>
          <li class="combo__option" role="option" data-value="Europe/Samara" data-ui-search="UTC+4">Самара <small>UTC+4</small></li>
          <li class="combo__option" role="option" data-value="Asia/Yekaterinburg" data-ui-search="UTC+5">Екатеринбург <small>UTC+5</small></li>
          <li class="combo__option" role="option" data-value="Asia/Novosibirsk" data-ui-search="UTC+7">Новосибирск <small>UTC+7</small></li>
          <li class="combo__option" role="option" data-value="Asia/Irkutsk" data-ui-search="UTC+8">Иркутск <small>UTC+8</small></li>
          <li class="combo__option" role="option" data-value="Asia/Vladivostok" data-ui-search="UTC+10">Владивосток <small>UTC+10</small></li>
        </ul>
        <p class="combo__empty" hidden>Ничего не найдено</p>
      </div>
    </div>
    <p class="field__hint">Время встреч в приглашениях показывается в этом поясе.</p>
  </div>
</form>
Выбор участника без выбранного значения
<div class="field">
  <label class="field__label" for="cb-host">Организатор</label>
  <div class="combo" data-ui-combobox>
    <input class="field__input combo__input" type="text" id="cb-host" role="combobox" aria-expanded="false" aria-controls="cb-host-list" aria-autocomplete="list" autocomplete="off" placeholder="Имя или e-mail">
    <input type="hidden" name="host">
    <button class="combo__toggle" type="button" tabindex="-1" aria-label="Показать все варианты" aria-expanded="false" aria-controls="cb-host-list">▾</button>
    <div class="combo__pop" hidden>
      <ul class="combo__list" id="cb-host-list" role="listbox" aria-label="Сотрудники">
        <li class="combo__option" role="option" data-value="anna" data-ui-search="anna@example.com">Анна Королёва <small>anna@example.com</small></li>
        <li class="combo__option" role="option" data-value="ivan" data-ui-search="ivan@example.com">Иван Петров <small>ivan@example.com</small></li>
        <li class="combo__option" role="option" data-value="maria" data-ui-search="maria@example.com">Мария Сидорова <small>maria@example.com</small></li>
        <li class="combo__option" role="option" data-value="oleg" data-ui-search="oleg@example.com" aria-disabled="true">Олег Смирнов <small>в отпуске</small></li>
      </ul>
      <p class="combo__empty" hidden>Сотрудник не найден</p>
    </div>
  </div>
</div>

Установка

bukatchuk-ui add combobox

Вместе с компонентом установятся: tokens, fonts, base, core, field.

Файлы

ФайлНазначение
combobox.cssстили
combobox.jsскрипт
example.htmlобразец разметки, в проект не копируется
combobox.jinja.htmlвставка для Jinja

Клавиши

КлавишаДействие
↓открыть список или перейти к следующему варианту
↑перейти к предыдущему варианту
Enterвыбрать подсвеченный вариант
Escзакрыть список; повторное нажатие очищает поле
Tabзакрыть список и перейти дальше

Макрос для Jinja

{#- Поле с поиском. options — список (value, label[, note]) или словарей {value, label, note, search, disabled};
    selected — выбранное значение. Значение уходит в скрытом поле name; нужен скрипт combobox. -#}
{% macro combobox(name, label, options, selected=None, placeholder='', empty='Ничего не найдено', hint=None, id=None) -%}
{%- set cid = id or ('cb-' ~ name) -%}
<div class="field">
  <label class="field__label" for="{{ cid }}">{{ label }}</label>
  <div class="combo" data-ui-combobox>
    {%- set ns = namespace(text='') %}
    {%- for o in options %}
      {%- set v = o.value if o is mapping else o[0] -%}
      {%- if v == selected %}{% set ns.text = o.label if o is mapping else o[1] %}{% endif %}
    {%- endfor %}
    <input class="field__input combo__input" type="text" id="{{ cid }}" role="combobox" aria-expanded="false" aria-controls="{{ cid }}-list" aria-autocomplete="list" autocomplete="off"{% if placeholder %} placeholder="{{ placeholder }}"{% endif %}{% if hint %} aria-describedby="{{ cid }}-h"{% endif %} value="{{ ns.text }}">
    <input type="hidden" name="{{ name }}" value="{{ selected if selected is not none else '' }}">
    <button class="combo__toggle" type="button" tabindex="-1" aria-label="Показать все варианты" aria-expanded="false" aria-controls="{{ cid }}-list">▾</button>
    <div class="combo__pop" hidden>
      <ul class="combo__list" id="{{ cid }}-list" role="listbox" aria-label="{{ label }}">
        {%- for o in options %}
        {%- set v = o.value if o is mapping else o[0] %}
        {%- set t = o.label if o is mapping else o[1] %}
        {%- set note = o.note if o is mapping else (o[2] if o|length > 2 else None) %}
        {%- set search = o.search if o is mapping else None %}
        <li class="combo__option" role="option" data-value="{{ v }}"{% if search %} data-ui-search="{{ search }}"{% endif %}{% if v == selected %} aria-selected="true" data-ui-default{% endif %}{% if o is mapping and o.disabled %} aria-disabled="true"{% endif %}>{{ t }}{% if note %} <small>{{ note }}</small>{% endif %}</li>
        {%- endfor %}
      </ul>
      <p class="combo__empty" hidden>{{ empty }}</p>
    </div>
  </div>
  {%- if hint %}
  <p class="field__hint" id="{{ cid }}-h">{{ hint }}</p>
  {%- endif %}
</div>
{%- endmacro %}