Toggle

Группа кнопок переключателей, хорошо подойдет для выбора из небольшого списка (до пяти вариантов). A group of buttons, well suited for selecting from a small list (up to five options).

Import Permalink to "Import"

js
import ProximaToggle from 'proxima-vue/toggle';

Playground Permalink to "Playground"

Select item
value: ''
Props
Label position
View
Round
Shadow
Click effect
js
import { ref } from 'vue';
import ProximaToggle from 'proxima-vue/toggle';

const value = ref('');
const options = ['one', 'two', 'three'];
html
<ProximaToggle
  label="Select item"
  :options="options"
  v-model="value"
/>

Options Permalink to "Options"

В компонент можно передать простой массив строк или чисел: You can simply pass an array of strings or numbers:

js
const simpleOptions = ['one', 'two', 'three']; // or [1, 2, 3]

Или массив объектов, где можно указать иконку с параметрами, атрибуты поля, лейбл, заблокировать определенный вариант: Or an array of objects where you can specify an icon with parameters, field attributes, a label, or disable a certain option:

js
const complexOptions = [
  { label: 'one', value: '1' },
  { label: 'two', value: '2' },
  { label: 'three', value: '3', disabled: true },
];

const fullOptionExample = {
  value: 1,
  label: 'one',
  labelVisuallyHidden: true,
  icon: 'svg',
  iconProps: { width: '16', height: '16' },
  inputAttrs: { 'data-id': 'value' },
  theme: 'bright',
  disabled: true,
};
ts
interface ProximaToggleOption {
  value: any
  label?: string
  labelVisuallyHidden?: boolean
  icon?: ProximaDynamicComponent
  iconProps?: ProximaDynamicProps
  inputAttrs?: ProximaDynamicAttrs
  disabled?: boolean
  theme?: string
}

Multiple Permalink to "Multiple"

value: []
js
import { ref } from 'vue';
import ProximaToggle from 'proxima-vue/toggle';

const value = ref([]);
html
<ProximaToggle
  :options="['Pear', 'Apple', 'Orange']"
  v-model="value"
/>

Skeleton Permalink to "Skeleton"

Режим плейсхолдера во время загрузки Placeholder mode on loading

Атрибут data‑ghost требует The attribute data‑ghost requires ghost.css

Select item
html

<div data-ghost="true" inert>
  <ProximaToggle
    label="Select item"
    :options="['one', 'two', 'three']"
  />
</div>

Indeterminate Permalink to "Indeterminate"

Специальный пропс для состояния indeterminate: A special prop for indeterminate state:

Select item
value: ''
js
import { ref } from 'vue';
import ProximaToggle from 'proxima-vue/toggle';

const value = ref('');
html
<ProximaToggle
  :options="['one', 'two', 'three']"
  :indeterminate="!value"
  v-model="value"
/>
Accessibility Permalink to "Accessibility"

Компонент использует radio и checkbox поля, они скрыты визуально, но доступны для скринридеров, для описания всей группы используется label, его также можно визуально скрыть: The component uses radio and checkbox inputs, they are hidden visually, but are accessible to screen readers, a label is used to describe the entire group, it can also be visually hidden:

Для работы visually‑hidden требуется The prop visually‑hidden requires accessibility.css

html
<ProximaToggle
  label="Heading to identify the group"
  label-visually-hidden
/>

Если же требуется расширенное описание для скринридеров, то можно использовать атрибут If you need an extended description for screen readers, you can use the attribute aria‑describedby

BEM Permalink to "BEM"

Блок компонента toggle, модификаторы (создаются автоматически на основе пропсов): Component block toggle, modifiers (automatically created based on props):

CSS Permalink to "CSS"

Слой компонента @layer proxima.toggle, также вы можете гибко cтилизовать компонент через кастомные свойства: Component layer @layer proxima.toggle, also you can style the component flexibly through custom properties:

css
--toggle-accent-color: var(--app-accent-color);
--toggle-button-width: auto;

/* Background */
--toggle-background: var(--app-field-background);
--toggle-view-line-background: transparent;

/* Border */
--toggle-border-color: var(--app-field-border-color);
--toggle-border-style: solid;
--toggle-border-width: 1px;

/* Radius soft */
--toggle-border-radius-divider: 16;
--toggle-border-radius: calc(
  var(--toggle-size) / var(--toggle-border-radius-divider)
);

/* Shadow soft */
--toggle-box-shadow-soft-size: 0.0625rem 0.0625rem 0.25rem;
--toggle-box-shadow-soft-color: rgba(0, 0, 0, 0.1);
--toggle-view-line-box-shadow-soft-size: 0;

/* Header */
--toggle-header-padding-x: 0;
--toggle-header-margin-y-end: calc(
  var(--toggle-label-font-size) * 0.375
);
--toggle-label-aside-width-multiplier: 10;
--toggle-label-aside-width: calc(
  var(--toggle-label-font-size) *
  var(--toggle-label-aside-width-multiplier)
);

/* Label */
--toggle-label-color: var(--app-label-color);
--toggle-label-letter-spacing: normal;
--toggle-label-line-height: 1.2;
--toggle-label-cursor: pointer;

/* Button flex */
--toggle-button-align-items: center;
--toggle-button-justify-content: center;
--toggle-button-flex-direction: row;
--toggle-button-gap: 0.375em;

/* Button padding */
--toggle-padding-y: 0;
--toggle-padding-x-divider: 2.25;
--toggle-padding-x: calc(
  var(--toggle-size) / var(--toggle-padding-x-divider)
);

/* Button text */
--toggle-font-family: inherit;
--toggle-font-weight: 400;
--toggle-text-color: var(--app-field-color);
--toggle-text-transform: none;
--toggle-letter-spacing: normal;

/* Diff */
--toggle-transition:
  color 200ms,
  background-color 200ms,
  border-color 200ms;

/*
  States
*/

/* Indeterminate */
--toggle-indeterminate-background: var(--toggle-background);
--toggle-indeterminate-border-color: rgba(207, 212, 217, 0.75);
--toggle-indeterminate-text-color: #8c8e90;

/* Disabled */
--toggle-disabled-background: var(--toggle-background);
--toggle-disabled-border-color: var(--toggle-border-color);
--toggle-disabled-text-color: var(--toggle-text-color);
--toggle-disabled-opacity: var(--app-disabled-opacity);

/* Checked */
--toggle-checked-background-opacity: 0.08;
--toggle-checked-background: color-mix(in srgb,
  var(--toggle-accent-color), transparent var(--toggle-checked-background-opacity)
);
--toggle-checked-border-color: var(--toggle-accent-color);
--toggle-checked-text-color: var(--toggle-accent-color);
--toggle-checked-z-index: 2;

/* Hover */
--toggle-hover-background: var(--toggle-background);
--toggle-hover-border-color: var(--toggle-accent-color);
--toggle-hover-text-color: var(--toggle-accent-color);
--toggle-hover-z-index: 1;

/* Focus highlight */
--toggle-highlight-style: var(--app-highlight-style);
--toggle-highlight-color: var(--app-highlight-color);
--toggle-highlight-size: var(--app-highlight-size);

--toggle-focus-border-color: var(--toggle-accent-color);
--toggle-focus-z-index: 3;

/* Tab focus outline */
--toggle-outline-offset: var(--app-outline-offset);
--toggle-outline-size: var(--app-outline-size);
--toggle-outline-style: var(--app-outline-style);
--toggle-outline-color: var(--app-outline-color);

/*
  Sizes
*/

--toggle-size-xxs: 1.875rem;
--toggle-font-size-xxs: 0.75rem;
--toggle-label-font-size-xxs: 0.75rem;

--toggle-size-xs: 2.25rem;
--toggle-font-size-xs: 0.875rem;
--toggle-label-font-size-xs: 0.8125rem;

--toggle-size-s: 2.5rem;
--toggle-font-size-s: 0.875rem;
--toggle-label-font-size-s: 0.875rem;

/* Normal */
--toggle-size: 2.75rem;
--toggle-font-size: 1rem;
--toggle-label-font-size: 0.875rem;

--toggle-size-m: 3rem;
--toggle-font-size-m: 1rem;
--toggle-label-font-size-m: 1rem;

--toggle-size-l: 3.375rem;
--toggle-font-size-l: 1.125rem;
--toggle-label-font-size-l: 1rem;

--toggle-size-xl: 3.75rem;
--toggle-font-size-xl: 1.25rem;
--toggle-label-font-size-xl: 1.125rem;

--toggle-size-xxl: 4.125rem;
--toggle-font-size-xxl: 1.375rem;
--toggle-label-font-size-xxl: 1.25rem;

/*
  Flags (0 or 1, based on props)
*/

--toggle-is-label-above: 0;
--toggle-is-label-aside: 0;

--toggle-is-view-plain: 0;
--toggle-is-view-line: 0;

--toggle-is-indeterminate: 0;
--toggle-is-disabled: 0;
--toggle-is-hover: 0;
--toggle-is-focus: 0;
--toggle-is-checked: 0;
--toggle-is-full-round: 0;
Locale Permalink to "Locale"

Компонент использует токены локализации: The component uses localization tokens:


js
{
  selectRequired: "Choose one of the options",
}
Props Permalink to "Props"
ts
interface ProximaToggleProps {
  id?: string
  modelValue?: any
  options?: ProximaToggleOption[] | string[] | number[]
  label?: string
  labelPosition?: 'above' | 'aside'
  labelVisuallyHidden?: boolean
  disabled?: boolean
  required?: boolean
  indeterminate?: boolean
  view?: 'plain' | 'line'
  size?: ProximaSize
  round?: ProximaRound
  shadow?: ProximaShadow
  effect?: ProximaClickEffect
  theme?: string
}
Events Permalink to "Events"
html
<ProximaToggle
  @update:modelValue="onToggleValueUpdate"
  @focus="onToggleFocus"
  @blur="onToggleBlur"
/>
js
const onToggleValueUpdate = (modelValue) => {};
const onToggleFocus = (event) => {};
const onToggleBlur = (event) => {};
ts
type Emits = {
  'update:modelValue': (modelValue: any) => void
  'focus': (event: FocusEvent) => void
  'blur': (event: FocusEvent) => void
}
Slots Permalink to "Slots"
html
<ProximaToggle>
  <template #prepend="slotProps">
    you code (prepend to inner)
  </template>

  <template #label="slotProps">
    you code (replaced label)
  </template>

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

  <template #option-icon="{ option, checked, ...slotProps }">
    you code (replaced option icon)
  </template>

  <template #option-label="{ option, checked, ...slotProps }">
    you code (replaced option label)
  </template>

  <template #content="slotProps">
    you code (append to content)
  </template>
</ProximaToggle>
ts
type SlotProps = {
  id: string
  hasLabel: boolean
  hasHeader: boolean
  isValid: boolean
  isFocused: boolean
  isMultiple: boolean
  isDisabled: boolean
  firstCheckedIndex: number
  firstEnabledIndex: number
  options: ProximaToggleOption[]
  errorMessage: string
  value: any
  focus: () => void
  blur: () => void
}
Expose Permalink to "Expose"
html
<ProximaToggle ref="toggle" />
ts
import { ref, unref, onMounted } from 'vue';
import ProximaToggle from 'proxima-vue/toggle';

const toggle = ref({} as InstanceType<typeof ProximaToggle>);

onMounted(() => {
  unref(toggle).checkFocus(); // false
  unref(toggle).focus();
  unref(toggle).checkFocus(); // true
});
ts
type ProximaToggleInstance = {
  getErrorMessage: () => string
  getContainer: () => HTMLFieldSetElement | null
  getValue: () => any
  getId: () => string
  getFirstCheckedElement: () => HTMLInputElement | null
  getFirstEnabledElement: () => HTMLInputElement | null
  checkValidity: () => boolean
  checkFocus: () => boolean
  focus: () => void
  blur: () => void
}
View source on GitHub