Switch
Переключатель между двумя состояниями или состоянием включения‑выключения. Used for switching between two states or on‑off state.
Import Permalink to "Import"
import ProximaSwitch from 'proxima-vue/switch';
Playground Permalink to "Playground"
import { ref } from 'vue';
import ProximaSwitch from 'proxima-vue/switch';
const value = ref(true);
<ProximaSwitch
label="Check me"
v-model="value"
/>
Custom values Permalink to "Custom values"
Вы можете указать любые true
и false
значения: You can specify any true
and false
values:
value: 'yes'
import { ref } from 'vue';
import ProximaSwitch from 'proxima-vue/switch';
const value = ref('yes');
<ProximaSwitch
label="Check me"
true-value="yes"
false-value="no"
v-model="value"
/>
Multiple Permalink to "Multiple"
Переключатель будет добавлять/удалять true‑value
из массива: The switch will add/remove true‑value
from the array:
value: []
import { ref } from 'vue';
import ProximaSwitch from 'proxima-vue/switch';
const value = ref([]);
<ProximaSwitch
label="Check one"
true-value="one"
v-model="value"
/>
<ProximaSwitch
label="Check two"
true-value="two"
v-model="value"
/>
Text and icon Permalink to "Text and icon"
В специальные слоты checked
и unchecked
можно передать иконки или текст: You can specify icons or text to special checked
and unchecked
slots:
import { ref } from 'vue';
import ProximaSwitch from 'proxima-vue/switch';
import ProximaIconCheck from 'proxima-vue/icon/check';
import ProximaIconCross from 'proxima-vue/icon/cross';
const value = ref(false);
<ProximaSwitch
label="Check me"
v-model="value"
>
<template #checked>YES</template>
<template #unchecked>NO</template>
</ProximaSwitch>
<ProximaSwitch
label="Check me"
v-model="value"
>
<template #checked>
<ProximaIconCheck />
</template>
<template #unchecked>
<ProximaIconCross />
</template>
</ProximaSwitch>
Pending Permalink to "Pending"
Режим ожидания во время запроса: Pending mode on request:
import { ref } from 'vue';
import ProximaSwitch from 'proxima-vue/switch';
import ProximaSpinner from 'proxima-vue/spinner';
const isPending = ref(true);
<ProximaSwitch
label="Check me"
:inert="isPending"
>
<template #thumb>
<ProximaSpinner v-if="isPending" />
</template>
</ProximaSwitch>
Skeleton Permalink to "Skeleton"
Режим плейсхолдера во время загрузки: Placeholder mode on loading:
Атрибут data‑ghost требует The attribute data‑ghost requires ghost.css
<div data-ghost="true" inert>
<ProximaSwitch
label="Check me"
/>
</div>
Indeterminate Permalink to "Indeterminate"
Специальный пропс для состояния indeterminate
: A special prop for indeterminate
state:
value: ''
import { ref } from 'vue';
import ProximaSwitch from 'proxima-vue/switch';
const value = ref('');
<ProximaSwitch
label="Do you want to enable notifications?"
true-value="yes"
false-value="no"
:indeterminate="value === ''"
v-model="value"
/>
Accessibility Permalink to "Accessibility"
Компонент использует checkbox
поле с role="switch"
, оно скрыто визуально, но доступно для вспомогательных технологий, для описания поля используется label
, его также можно визуально скрыть: The component uses checkbox
input with role="switch"
, it is hidden visually, but available for assistive technologies, a label
is used to describe the input, it can also be visually hidden:
Для работы visually‑hidden требуется The prop visually‑hidden requires accessibility.css
<ProximaSwitch
label="Label only for assistive technologies"
label-visually-hidden
/>
Если же требуется расширенное описание, то можно использовать пропс describedby
, который добавляет полю атрибут aria‑describedby: If you need an extended description, you can use the describedby
prop, which adds aria‑describedby attribute to the input:
<ProximaSwitch
label="Check me"
describedby="my-hidden-description"
/>
<p id="my-hidden-description" hidden>
The extended description for assistive technologies can be hidden
</p>
BEM Permalink to "BEM"
Блок компонента switch
, модификаторы (создаются автоматически на основе пропсов): Component block switch
, modifiers (automatically created based on props):
switch_focused
switch_checked
switch_unchecked
switch_indeterminate
switch_required
switch_enabled
switch_disabled
switch_has_label
switch_has_effect
switch_label_after
switch_label_before
switch_effect_none
switch_effect_ripple
switch_effect_pulse
switch_view_plain
switch_view_slider
switch_size_xxs
switch_size_xs
switch_size_s
switch_size_normal
switch_size_m
switch_size_l
switch_size_xl
switch_size_xxl
switch_round_full
switch_round_soft
switch_round_none
switch_shadow_none
switch_shadow_soft
switch_align_start
switch_align_center
switch_align_end
switch_theme_[name]
CSS Permalink to "CSS"
Слой компонента @layer proxima.switch
, также вы можете гибко cтилизовать компонент через кастомные свойства: Component layer @layer proxima.switch
, also you can style the component flexibly through custom properties:
--switch-background: #bfbfbf;
--switch-value-color: #fff;
--switch-accent-color: var(--app-accent-color);
--switch-min-width-multiplier: 1.85;
--switch-min-width: calc(
var(--switch-size) * var(--switch-min-width-multiplier) -
var(--switch-padding)
));
--switch-gap: calc(var(--switch-size) / 2);
--switch-transition: background-color 200ms ease;
/* Soft round */
--switch-border-radius: calc(var(--switch-size) / 4);
/* Spinner and icon */
--switch-spinner-size: 72%;
--switch-icon-size: 80%;
/* Effect */
--switch-effect-pulse-color: var(--switch-background);
--switch-effect-ripple-color: #000;
--switch-effect-z-index: 2;
/* Slider view */
--switch-track-margin-y: 25%;
--switch-track-margin-x: var(--switch-padding);
/* Border */
--switch-border-width: 0;
--switch-border-style: solid;
--switch-border-color: transparent;
/* Label */
--switch-label-line-height: 1.3;
--switch-label-color: var(--app-label-color);
--switch-label-align-self: center;
/* Thumb */
--switch-thumb-background: #fff;
--switch-thumb-color: #000;
--switch-thumb-padding: 0;
--switch-thumb-border-radius: inherit;
--switch-thumb-box-shadow: 0 0.125rem 0.25rem 0 rgba(0, 0, 0, 0.2);
--switch-thumb-transition: inset 250ms cubic-bezier(0.22, 1, 0.36, 1);
/* Value */
--switch-value-color: #fff;
--switch-value-padding-x: 1em;
--switch-value-padding-y: 0;
--switch-value-transition: transform 250ms cubic-bezier(0.22, 1, 0.36, 1);
/* Shadow */
--switch-box-shadow-soft-size: 0 0.0625rem 0.25rem;
--switch-box-shadow-soft-color: rgba(0, 0, 0, 0.15);
/*
States
*/
/* Checked */
--switch-checked-background: var(--switch-accent-color);
--switch-checked-value-color: var(--switch-value-color);
--switch-checked-thumb-background: var(--switch-thumb-background);
--switch-checked-thumb-color: var(--switch-thumb-color);
/* Hover */
--switch-hover-mix-color: #000;
--switch-hover-mix-opacity: 0.1;
--switch-hover-background: color-mix(in srgb,
var(--switch-background), var(--switch-hover-mix-color) var(--switch-hover-mix-opacity)
);
/* Disabled */
--switch-disabled-opacity: var(--app-disabled-opacity);
--switch-disabled-background: var(--switch-background);
--switch-disabled-thumb-background: var(--switch-thumb-background);
/* Focus highlight */
--switch-highlight-offset: var(--app-highlight-offset);
--switch-highlight-style: var(--app-highlight-style);
--switch-highlight-size: var(--app-highlight-size);
--switch-highlight-color: var(--app-highlight-color);
/* Tab focus outline */
--switch-outline-offset: var(--app-outline-offset);
--switch-outline-size: var(--app-outline-size);
--switch-outline-style: var(--app-outline-style);
--switch-outline-color: var(--app-outline-color);
/*
Sizes
*/
--switch-size-xxs: 1rem;
--switch-padding-xxs: 0.125rem;
--switch-label-font-size-xxs: 0.75rem;
--switch-value-font-size-xxs: 0.625rem;
--switch-state-icon-size-xxs: 0.5rem;
--switch-size-xs: 1.125rem;
--switch-padding-xs: 0.125rem;
--switch-label-font-size-xs: 0.8125rem;
--switch-value-font-size-xs: 0.625rem;
--switch-state-icon-size-xs: 0.5rem;
--switch-size-s: 1.25rem;
--switch-padding-s: 0.125rem;
--switch-label-font-size-s: 0.875rem;
--switch-value-font-size-s: 0.625rem;
--switch-state-icon-size-s: 0.5rem;
/* Normal */
--switch-size: 1.375rem;
--switch-padding: 0.125rem;
--switch-label-font-size: 0.875rem;
--switch-value-font-size: 0.75em;
--switch-state-icon-size: 0.625rem;
--switch-size-m: 1.625rem;
--switch-padding-m: 0.1875rem;
--switch-label-font-size-m: 1rem;
--switch-value-font-size-m: 0.875rem;
--switch-state-icon-size-m: 0.625rem;
--switch-size-l: 1.875rem;
--switch-padding-l: 0.25rem;
--switch-label-font-size-l: 1.125rem;
--switch-value-font-size-l: 0.875rem;
--switch-state-icon-size-l: 0.75rem;
--switch-size-xl: 2.25rem;
--switch-padding-xl: 0.25rem;
--switch-label-font-size-xl: 1.25rem;
--switch-value-font-size-xl: 1rem;
--switch-state-icon-size-xl: 0.875rem;
--switch-size-xxl: 2.5rem;
--switch-padding-xxl: 0.25rem;
--switch-label-font-size-xxl: 1.375rem;
--switch-value-font-size-xxl: 1.125rem;
--switch-state-icon-size-xxl: 1rem;
/*
Flags (0 or 1, based on props)
*/
--switch-has-effect: 0;
--switch-is-view-plain: 0;
--switch-is-view-slider: 0;
--switch-is-checked: 0;
--switch-is-unchecked: 0;
--switch-is-indeterminate: 0;
--switch-is-disabled: 0;
--switch-is-focus: 0;
--switch-is-hover: 0; /* ! */
--switch-is-active: 0; /* ! */
/*
[!] Available for .switch__content not on .switch
*/
Theme Permalink to "Theme"
Используя кастомные свойства и специальный пропс theme
можно легко создавать свои темы: By using custom properties and the prop theme
, you can easily create your own themes:
<ProximaSwitch
label="Check me"
theme="ios"
/>
.switch_theme_ios {
--switch-label-color: #8d8d92;
--switch-background: #dfdfe0;
--switch-value-color: #b8b8b8;
--switch-checked-value-color: #fff;
--switch-accent-color: #35c759;
--switch-thumb-box-shadow: 0 0.125rem 0.125rem rgba(0, 0, 0, 0.1);
--switch-min-width-multiplier: 1.75;
--switch-hover-mix-opacity: 0.05;
}
Locale Permalink to "Locale"
Компонент использует токены локализации: The component uses localization tokens:
{
switchRequired: "The switch must be activated",
}
Props Permalink to "Props"
interface ProximaSwitchProps {
id?: string
inputAttrs?: InputHTMLAttributes
trueValue?: any
falseValue?: any
modelValue?: any
label?: string
labelPosition?: 'before' | 'after'
labelVisuallyHidden?: boolean
describedby?: string
hasStateIcons?: boolean
disabled?: boolean
required?: boolean
indeterminate?: boolean
align?: ProximaAlign
view?: 'plain' | 'slider'
size?: ProximaSize
round?: ProximaRound
shadow?: ProximaShadow
effect?: ProximaClickEffect
theme?: string
}
Events Permalink to "Events"
<ProximaSwitch
@update:modelValue="onSwitchUpdate"
@focus="onSwitchFocus"
@blur="onSwitchBlur"
/>
const onSwitchUpdate = (modelValue) => {};
const onSwitchFocus = (event) => {};
const onSwitchBlur = (event) => {};
type Emits = {
'update:modelValue': (modelValue: any) => void
'focus': (event: FocusEvent) => void
'blur': (event: FocusEvent) => void
}
Slots Permalink to "Slots"
<ProximaSwitch>
<template #prepend="slotProps">
you code (prepend to content)
</template>
<template #checked="slotProps">
you code (visible when checked)
</template>
<template #unchecked="slotProps">
you code (visible when unchecked)
</template>
<template #thumb="slotProps">
you code (append to thumb)
</template>
<template #label="slotProps">
you code (replaced label text)
</template>
</ProximaSwitch>
type SlotProps = {
id: string
hasEffect: boolean
hasLabel: boolean
hasUncheckedValue: boolean
hasCheckedValue: boolean
hasStateIcons: boolean
isIndeterminate: boolean
isMultiple: boolean
isChecked: boolean
isFocused: boolean
isValid: boolean
errorMessage: string
value: any
focus: () => void
blur: () => void
}
Expose Permalink to "Expose"
<ProximaSwitch ref="switcher" />
import { ref, unref, onMounted } from 'vue';
import ProximaSwitch from 'proxima-vue/switch';
const switcher = ref({} as InstanceType<typeof ProximaSwitch>);
onMounted(() => {
unref(switcher).checkFocus(); // false
unref(switcher).focus();
unref(switcher).checkFocus(); // true
});
type ProximaSwitchInstance = {
getErrorMessage: () => string
getContainer: () => HTMLDivElement | null
getElement: () => HTMLInputElement | null
getValue: () => any
getId: () => string
checkValidity: () => boolean
checkFocus: () => boolean
checked: () => boolean
focus: () => void
blur: () => void
}