Создайте свою собственную библиотеку пользовательского интерфейса Vue с помощью Unstyled PrimeVue Core и Tailwind CSS
Обертывание компонентов пользовательского интерфейса для инкапсуляции настраиваемого поведения — распространенная практика при создании собственной библиотеки пользовательского интерфейса, особенно в более крупных командах, где общая библиотека используется среди множества приложений. Основным преимуществом этого подхода является отделение зависимости от сторонней библиотеки, поскольку приложения-потребители вместо этого зависят от общей библиотеки.
Нестилизованное ядро PrimeVue и Tailwind CSS станут идеальным набором инструментов, если вам нужно создать собственную библиотеку пользовательского интерфейса. Основная идея состоит в том, чтобы создать компонент пользовательского интерфейса, обернув компонент PrimeVue, передать свои реквизиты как промежуточные и настроить сквозную предустановку Tailwind локально, а не глобальную конфигурацию.
Тумблер
Давайте создадим наш собственный компонент ToggleSwitch
, вдохновленный Material Design. Для этого мы будем использовать компонент PrimeVue InputSwitch.
Шаблон
Раздел шаблона состоит из гибкого контейнера-оболочки, встроенной метки и PrimeVue InputSwitch
. Обратите внимание на использование v-bind="$attrs"
, поскольку мы хотели бы применить любое свойство, переданное нашему собственному компоненту, к базовому InputSwitch
, например, v-model
и v-on
событиям. Компонент здесь отвечает за основную функциональность и доступность, а мы фокусируемся на стандартизации требований к дизайну.
<template>
<div class="flex items-center gap-4">
<label :for="$attrs.inputId">{{ label }}</label>
<InputSwitch v-bind="$attrs" />
</div>
</template>
Скрипт
Скрипт устанавливает inheritAttrs
значение false
, в противном случае свойства падения применяются к основному элементу контейнера div
. Дополнительные реквизиты, такие как метка, включены как реквизиты нашего собственного компонента.
Предварительные настройки
Итак, вся проводка на месте, пора применить наш собственный стиль, вдохновленный дизайном материалов, реализованных с помощью утилит Tailwind. Стиль применяется локально с помощью свойства InputSwitch
, поскольку мы используем локальную предустановку, отключив слияние с глобальной предустановкой с помощью ptOptions
. Для этого мы будем использовать пресет переключения материала из галереи пресетов CSS PrimeVue Tailwind
.
<template>
<div class="flex items-center gap-4">
<label :for="$attrs.inputId">{{ label }}</label>
<InputSwitch v-bind="$attrs" :pt="preset" :ptOptions="{ mergeSections: false, mergeProps: false }" />
</div>
</template>
Предустановка представляет собой простую конфигурацию pt
, основанную на API-интерфейсе InputSwitch PassThrough
с некоторыми расширениями. Обратите внимание на использование attrs
для добавления режима акцентов, которого нет в API PrimeVue InputSwitch
. Мы можем использовать произвольные атрибуты для добавления функциональности к компонентам, которые мы обертываем, не дожидаясь, пока специалист по сопровождению библиотеки компонентов добавит это за нас. Это отличный пример философии PrimeVue
, предоставляющей стороннюю библиотеку пользовательского интерфейса, которую легко настраивать, как если бы это была собственная библиотека.
<script setup>
defineOptions({
inheritAttrs: false
});
defineProps(['label']);
const preset = {
root: ({ props }) => ({
class: [
'inline-block relative',
'w-10 h-4',
{
'opacity-40 select-none pointer-events-none cursor-default': props.disabled
}
]
}),
slider: ({ props, state, attrs }) => ({
class: [
// Position
'absolute top-0 left-0 right-0 bottom-0 before:transform',
{ 'before:translate-x-5': props.modelValue },
{ 'before:-translate-x-1': !props.modelValue },
// Shape
'rounded-2xl',
// Before:
'before:absolute before:top-1/2',
'before:-mt-3',
'before:h-6 before:w-6',
'before:rounded-full',
'before:duration-200',
'before:flex before:justify-center before:items-center',
'before:[text-shadow:0px_0px_WHITE] before:text-transparent',
{ 'before:ring-4': state.focused },
{
"before:bg-surface-500 before:dark:bg-surface-500 before:content-['➖']": !props.modelValue,
"before:content-['✔️']": props.modelValue,
'before:bg-violet-500 before:ring-violet-300': !attrs.type & props.modelValue,
'before:bg-amber-500 before:ring-amber-300': attrs.type === 'accent' && props.modelValue
},
// Colors
'border border-transparent',
{
'bg-surface-200 dark:bg-surface-400 before:ring-surface-200 dark:before:ring-surface-400': !props.modelValue,
'bg-violet-300': !attrs.type & props.modelValue,
'bg-amber-300': attrs.type === 'accent' && props.modelValue
},
// States
{
'hover:before:bg-surface-400 hover:dark:before:bg-surface-600': !props.modelValue,
'hover:before:bg-violet-600': !attrs.type & props.modelValue,
'hover:before:bg-amber-600': attrs.type === 'accent' && props.modelValue
},
// Transition
'transition-colors duration-200',
// Misc
'cursor-pointer'
]
})
};
</script>
Конечный результат
Давайте завершим это примером использования. Смотрите демонстрацию переключения материала, чтобы увидеть рабочий образец пресета, который мы использовали в этом компоненте.
<ToggleSwitch v-model="checked1" inputId="primary" label="Primary" />
<ToggleSwitch v-model="checked2" inputId="accent" label="Accent" type="accent" />