Combobox

Базовый комбобокс, в основе текстовое поле. Basic combobox component, based on a text field.

Import Permalink to "Import"

js
import ProximaCombobox from 'proxima-vue/field/combobox';

Playground Permalink to "Playground"

value: ''
Props
Label position
View
Round
Shadow
Actions visibility
js
import { ref } from 'vue';
import ProximaCombobox from 'proxima-vue/field/combobox';

const value = ref('');

const options = ['Ivan III', 'Vasili III', 'Ivan IV Vasilyevich', 'Feodor I', 'Boris Godunov', 'Feodor II', 'False Dmitry I', 'Vasili IV', 'Fedor Mstislavsky', 'Michael I', 'Alexei Mikhailovich', 'Feodor III', 'Ivan V', 'Sophia Alekseyevna', 'Peter the Great', 'Catherine I', 'Peter II', 'Anna Ioannovna', 'Ivan VI', 'Elizaveta Petrovna', 'Peter III', 'Catherine the Great', 'Paul I', 'Alexander I', 'Nicholas I', 'Alexander II', 'Alexander III', 'Nicholas II'];
html
<ProximaCombobox
  label="Select person"
  placeholder="Favorite tsar(evna) of Russia"
  :options="options"
  v-model="value"
/>

Options Permalink to "Options"

В компонент можно передать простой массив строк или объектов c указанием ключа для фильтра, по умолчанию это поле You can pass a simple array of strings or objects to the component, indicating the key for the filter; by default, this is the name:

value:
html
<ProximaCombobox
  label="Select person"
  placeholder="Who is Satoshi Nakamoto?"
  :options="candidates"
  filter-key="person.fullname"
  v-model="value"
/>
js
import { ref } from 'vue';
import ProximaCombobox from 'proxima-vue/field/combobox';

const value = ref();
const candidates = [
  { person: { fullname: 'Hal Finney' } },
  { person: { fullname: 'Nick Szabo' } },
  { person: { fullname: 'Adam Back' } },
  { person: { fullname: 'Len Sassaman' } },
  { person: { fullname: 'Bram Cohen' } },
  { person: { fullname: 'Dorian Nakamoto' } },
  { person: { fullname: 'Craig Wright' } },
  { person: { fullname: 'Elon Musk' } },
];

Max visible Permalink to "Max visible"

По умолчанию отображается 15 вариантов и текстовая подсказка об общем количестве, вы можете изменить это число, а также скрыть подсказку: By default, 15 options are displayed along with a text hint about the total quantity. You can change this number and also hide the count label:

html
<ProximaCombobox
  :max-visible-options="20"
  :has-count-label="false"
/>

Search Permalink to "Search"

В компонент можно передать свою функцию для поиска элемента: You can pass your own function to search for an element:

value:
html
<ProximaCombobox
  label="Select coin"
  placeholder="Favorite cryptocurrency"
  :search-filter="findCoinByNameAndCode"
  :options="coins"
  v-model="value"
/>
js
import { ref } from 'vue';
import ProximaCombobox from 'proxima-vue/field/combobox';

const findCoinByNameAndCode = (option, query) => {
  const str = [option.name, option.code].join(' ').toLowerCase();
  return str.includes(query.toLowerCase());
};

const value = ref();
const coins = [
  { name: 'Tether (TRC-20)', code: 'usdt' },
  { name: 'Bitcoin', code: 'btc' },
  { name: 'Toncoin', code: 'ton' },
  { name: 'Dogecoin', code: 'doge' },
  { name: 'Ethereum', code: 'eth' },
  { name: 'Litecoin', code: 'ltc' },
  { name: 'Dash', code: 'dash' },
  { name: 'Chia', code: 'xch' },
];

Pin Permalink to "Pin"

Вы можете передать функцию фильтр для закрепления определенных вариантов вверху списка: You can pass a filter function to pin certain options to the top of the list:

value:
html
<ProximaCombobox
  label="Select person"
  placeholder="Favorite tsar(evna) of Russia"
  :pin-filter="pinGreatPersons"
  :options="options"
  v-model="value"
/>
js
import { ref } from 'vue';
import ProximaCombobox from 'proxima-vue/field/combobox';

const pinGreatPersons = (name) => name.toLowerCase().includes('great');

const value = ref();
const options = ['Ivan III', 'Vasili III', 'Ivan IV Vasilyevich', 'Feodor I', 'Boris Godunov', 'Feodor II', 'False Dmitry I', 'Vasili IV', 'Fedor Mstislavsky', 'Michael I', 'Alexei Mikhailovich', 'Feodor III', 'Ivan V', 'Sophia Alekseyevna', 'Peter the Great', 'Catherine I', 'Peter II', 'Anna Ioannovna', 'Ivan VI', 'Elizaveta Petrovna', 'Peter III', 'Catherine the Great', 'Paul I', 'Alexander I', 'Nicholas I', 'Alexander II', 'Alexander III', 'Nicholas II'];

Disable Permalink to "Disable"

Вы можете передать функцию фильтр для блокировки определенных вариантов: You can pass a filter function to disable certain options:

value:
html
<ProximaCombobox
  label="Select person"
  placeholder="Favorite tsar(evna) of Russia"
  :disable-filter="disablePersons"
  :options="options"
  v-model="value"
/>
js
import { ref } from 'vue';
import ProximaCombobox from 'proxima-vue/field/combobox';

const disablePersons = (name) => name.toLowerCase().includes('ivan');

const value = ref();
const options = ['Ivan III', 'Vasili III', 'Ivan IV Vasilyevich', 'Feodor I', 'Boris Godunov', 'Feodor II', 'False Dmitry I', 'Vasili IV', 'Fedor Mstislavsky', 'Michael I', 'Alexei Mikhailovich', 'Feodor III', 'Ivan V', 'Sophia Alekseyevna', 'Peter the Great', 'Catherine I', 'Peter II', 'Anna Ioannovna', 'Ivan VI', 'Elizaveta Petrovna', 'Peter III', 'Catherine the Great', 'Paul I', 'Alexander I', 'Nicholas I', 'Alexander II', 'Alexander III', 'Nicholas II'];

Create Permalink to "Create"

Попап может содержать кнопку создания нового значения: The field popup may contain a button to create a new value:

Press Enter to create and select “”
city: ""
cities: [ "Saint Petersburg", "Barcelona", "New York" ]
html
<ProximaCombobox
  label="The most beautiful city"
  placeholder="You can add your city"
  :options="cities"
  has-create-button
  @create="createAndSelect"
  v-model="city"
/>
js
import { ref, unref } from 'vue';
import ProximaCombobox from 'proxima-vue/field/combobox';

const city = ref();
const cities = ref(['Saint Petersburg', 'Barcelona', 'New York']);

const createAndSelect = (name) => {
  unref(cities).push(name);
  city.value = name;
};

Fly search Permalink to "Fly search"

Для активации поиска на лету добавьте mode="fetch" и используйте функцию useProximaFlySearch, которая принимает в качестве аргумента метод поиска и возвращает необходимые параметры: To enable on‑the‑fly search, add mode="fetch" and use the useProximaFlySearch function, which takes a search method as an argument and returns the necessary parameters:

Анимация загрузки списка требуетList loading animation requires ghost.css

country:
html
<ProximaCombobox
  mode="fetch"
  label="Country"
  placeholder="Find country ..."
  :options="flySearchResults"
  :is-list-pending="isFlySearchPending"
  @update:filterValue="onFlySearchUpdate"
  v-model="country"
/>
js
import { ref } from 'vue';
import ProximaCombobox from 'proxima-vue/field/combobox';
import useProximaFlySearch from 'proxima-vue/composables/flySearch';

const country = ref();

const findCountry = async (query) => {
  const response = await fetch(`https://mocky.yoobe.ru/countries/find?name=${query}`);
  const results = await response.json();
  return results;
};

const { isFlySearchPending, onFlySearchUpdate, flySearchResults } =
  useProximaFlySearch(findCountry);

Accessibility Permalink to "Accessibility"

Поле имеет role="combobox" и атрибуты aria‑autocomplete="list", aria‑haspopup="listbox", aria‑controls, aria‑expanded, вспомогательные технологии обозначают активный элемент списка при навигации с клавиатуры благодаря атрибуту aria‑activedescendant. The field has role="combobox" and attributes aria‑autocomplete="list", aria‑haspopup="listbox", aria‑controls, aria‑expanded. Assistive technologies indicate the active list item during keyboard navigation with aria‑activedescendant attribute.

BEM Permalink to "BEM"

Компонент имеет свои модификаторы (создаются автоматически на основе пропсов): The component has its own modifiers (automatically created based on props):

CSS Permalink to "CSS"

css
--field-popup-background: var(--field-background);
--field-popup-color: var(--field-color);

--field-popup-overflow-y: auto;
--field-popup-scroll-padding-y-start: 0.25rem;
--field-popup-scroll-padding-y-end: 6rem;

--field-popup-footer-max-width: 24em;
--field-popup-footer-border-size: 1px;
--field-popup-footer-border-color: #eee;

--field-popup-margin-y-start: -0.25rem;

--field-popup-font-size-xxs: 0.75rem;
--field-popup-font-size-xs: 0.8125rem;
--field-popup-font-size-s: 0.875rem;
--field-popup-font-size: 0.875rem;
--field-popup-font-size-m: 0.875rem;
--field-popup-font-size-l: 1rem;
--field-popup-font-size-xl: 1.125rem;
--field-popup-font-size-xxl: 1.25rem;

/*
  Options
*/

--field-options-padding-x: 0.25rem;
--field-options-padding-y: 0.25rem;
--field-options-z-index: 1;

--field-option-padding-x: 0.875em;
--field-option-padding-y: 0.75em;

--field-option-gap: 1em;
--field-option-border-radius: 0.375rem;

--field-option-selected-color: var(--field-accent-color);
--field-option-hover-background: #f6f6f6;
--field-option-disabled-opacity: 0.4;

/* Create */
--field-option-create-padding-x: 1.25em;
--field-option-create-color: var(--field-accent-color);

/* Check icon */
--field-option-tick-order: 1;
--field-option-tick-size: 1.125em;
--field-option-tick-stroke-width: 2;
--field-option-tick-margin-x-start: auto;

/* Plus icon */
--field-option-plus-size: 1em;
--field-option-plus-stroke-width: 1.25;
--field-option-plus-margin-x-start: -0.375em;
Locale Permalink to "Locale"

Компонент использует токены локализации, вы можете передать другие токены или обычный текст через пропсы: The component uses localization tokens, and you can pass other tokens or plain text via props:

  • notfoundLabel
  • countLabel
  • createLabel
  • createDescription

js
{
  fieldCreateLabel: "Create “{query}”",
  fieldCreateDescription: "Press Enter to create and select “{query}”",
  fieldNotfoundLabel: "Nothing was found",
  fieldFilterCountLabel: "Showing {visibleCount} of {totalCount} items, refine your request to see the rest",
}
Props Permalink to "Props"
ts
interface ProximaComboboxProps<Option> {
  mode?: 'local' | 'fetch'
  filterKey?: string
  modelValue?: Option
  options?: Option[]
  required?: boolean
  maxVisibleOptions?: number
  notfoundLabel?: string
  countLabel?: string
  createLabel?: string
  createDescription?: string
  pinFilter?: (option: Option) => boolean
  searchFilter?: (option: Option, query: string) => boolean
  disableFilter?: (option: Option, modelValue?: Option) => boolean
  selectChecker?: (option: Option, modelValue?: Option) => boolean
  popupProps?: ProximaDynamicProps
  hasCreateButton?: boolean
  hasCountLabel?: boolean
  isListPending?: boolean
}
Slots Permalink to "Slots"
html
<ProximaCombobox>
  <template #popup-prepend="slotProps">
    you code (prepend to popup)
  </template>

  <template #popup="slotProps">
    you code (append to popup)
  </template>

  <template #popup-footer="{ id, ...slotProps }">
    you code (replaced popup footer)
  </template>

  <template #option="{ option, ...slotProps }">
    you code (replaced popup option)
  </template>
</ProximaCombobox>
ts
type SlotProps = {
  maxVisibleOptions: number
  filterValue: string
  pinnedOptions: Option[]
  unpinnedOptions: Option[]
  filteredOptions: Option[]
  visibleOptions: Option[]
  optionIndex: number
  notfoundLabel: string
  countLabel: string
  selectedLabel: string
  hasValue: boolean
  isNotfoundVisible: boolean
  isFilterCountVisible: boolean
  isPopupOpened: boolean
  isFlySearch: boolean
}
Expose Permalink to "Expose"

Поле поддерживает все методы текстового поля и свои собственные: The field supports all text field methods and some own:

html
<ProximaCombobox
  ref="combobox"
  :options="options"
  v-model="value"
/>
ts
import { ref, unref, onMounted } from 'vue';
import ProximaCombobox from 'proxima-vue/field/combobox';

const combobox = ref({} as InstanceType<typeof ProximaCombobox>);
const value = ref('');
const options = ['Bitcoin', 'Toncoin', 'Dogecoin'];

onMounted(() => {
  unref(combobox).checkOptionSelected('Bitcoin'); // false
  unref(combobox).pickOption('Bitcoin');
  unref(combobox).checkOptionSelected('Bitcoin'); // true
});
ts
type ProximaComboboxInstance = {
  checkOptionPinned: (option: any) => boolean
  checkOptionSelected: (option: any) => boolean
  checkOptionDisabled: (option: any) => boolean
  pickOption: (option: any) => void
  pickOptionByIndex: () => void
  scrollToOption: () => void
  setOptionIndex: (number) => void
  setPrevIndex: () => void
  setNextIndex: () => void
  setFirstIndex: () => void
  setFilterValue: (value: string) => void
  showPopup: () => void
  hidePopup: () => void
}

Extends Permalink to "Extends"

Данный компонент основан на текстовом поле и поддерживает его пропсы, события, слоты, БЭМ модификаторы и кастомные свойства. This component is based on a text field and supports its props, events, slots, BEM modifiers and custom properties.

View source on GitHub