Feat: Implementar paleta de colores por categoría en sliders
All checks were successful
build-and-deploy / build-and-deploy (push) Successful in 1m6s
All checks were successful
build-and-deploy / build-and-deploy (push) Successful in 1m6s
- Agregar composable useCategoryColors con 8 colores coordinados (light/dark) - Colores por categoría: Fragancia (lavanda), Aroma (verde menta), Sabor (rojo), Sabor Residual (naranja), Acidez (amarillo), Dulzor (rosa), Sensación en Boca (azul), Impresión Global (turquesa) - Eliminar hints de texto de SliderIntensidad (showDescription = false por defecto) - Aplicar colores dinámicos a headers y sliders de cada categoría - Aumentar font-weight de headers a 700 (bold) - Los colores se adaptan automáticamente al tema light/dark
This commit is contained in:
@@ -35,18 +35,20 @@
|
||||
|
||||
<!-- Sliders de Fragancia -->
|
||||
<div class="form-section">
|
||||
<h5 class="form-section-title cata-text">Fragancia</h5>
|
||||
<h5 class="form-section-title cata-text" :style="{ color: getCategoryColor('fragancia') }">Fragancia</h5>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<CataSliderIntensidad
|
||||
tipo="descriptiva"
|
||||
label="Descriptiva"
|
||||
:model-value="muestra.intensidades.fragancia.descriptiva"
|
||||
:color="getCategoryColor('fragancia')"
|
||||
@update:model-value="(v) => actualizarIntensidad('fragancia', 'descriptiva', v)"
|
||||
/>
|
||||
<CataSliderIntensidad
|
||||
tipo="afectiva"
|
||||
label="Afectiva"
|
||||
:model-value="muestra.intensidades.fragancia.afectiva"
|
||||
:color="getCategoryColor('fragancia')"
|
||||
@update:model-value="(v) => actualizarIntensidad('fragancia', 'afectiva', v)"
|
||||
/>
|
||||
</div>
|
||||
@@ -54,18 +56,20 @@
|
||||
|
||||
<!-- Sliders de Aroma -->
|
||||
<div class="form-section">
|
||||
<h5 class="form-section-title cata-text">Aroma</h5>
|
||||
<h5 class="form-section-title cata-text" :style="{ color: getCategoryColor('aroma') }">Aroma</h5>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<CataSliderIntensidad
|
||||
tipo="descriptiva"
|
||||
label="Descriptiva"
|
||||
:model-value="muestra.intensidades.aroma.descriptiva"
|
||||
:color="getCategoryColor('aroma')"
|
||||
@update:model-value="(v) => actualizarIntensidad('aroma', 'descriptiva', v)"
|
||||
/>
|
||||
<CataSliderIntensidad
|
||||
tipo="afectiva"
|
||||
label="Afectiva"
|
||||
:model-value="muestra.intensidades.aroma.afectiva"
|
||||
:color="getCategoryColor('aroma')"
|
||||
@update:model-value="(v) => actualizarIntensidad('aroma', 'afectiva', v)"
|
||||
/>
|
||||
</div>
|
||||
@@ -73,18 +77,20 @@
|
||||
|
||||
<!-- Sliders de Sabor -->
|
||||
<div class="form-section">
|
||||
<h5 class="form-section-title cata-text">Sabor</h5>
|
||||
<h5 class="form-section-title cata-text" :style="{ color: getCategoryColor('sabor') }">Sabor</h5>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<CataSliderIntensidad
|
||||
tipo="descriptiva"
|
||||
label="Descriptiva"
|
||||
:model-value="muestra.intensidades.sabor.descriptiva"
|
||||
:color="getCategoryColor('sabor')"
|
||||
@update:model-value="(v) => actualizarIntensidad('sabor', 'descriptiva', v)"
|
||||
/>
|
||||
<CataSliderIntensidad
|
||||
tipo="afectiva"
|
||||
label="Afectiva"
|
||||
:model-value="muestra.intensidades.sabor.afectiva"
|
||||
:color="getCategoryColor('sabor')"
|
||||
@update:model-value="(v) => actualizarIntensidad('sabor', 'afectiva', v)"
|
||||
/>
|
||||
</div>
|
||||
@@ -92,18 +98,20 @@
|
||||
|
||||
<!-- Sliders de Sabor Residual -->
|
||||
<div class="form-section">
|
||||
<h5 class="form-section-title cata-text">Sabor Residual</h5>
|
||||
<h5 class="form-section-title cata-text" :style="{ color: getCategoryColor('saborResidual') }">Sabor Residual</h5>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<CataSliderIntensidad
|
||||
tipo="descriptiva"
|
||||
label="Descriptiva"
|
||||
:model-value="muestra.intensidades.saborResidual.descriptiva"
|
||||
:color="getCategoryColor('saborResidual')"
|
||||
@update:model-value="(v) => actualizarIntensidad('saborResidual', 'descriptiva', v)"
|
||||
/>
|
||||
<CataSliderIntensidad
|
||||
tipo="afectiva"
|
||||
label="Afectiva"
|
||||
:model-value="muestra.intensidades.saborResidual.afectiva"
|
||||
:color="getCategoryColor('saborResidual')"
|
||||
@update:model-value="(v) => actualizarIntensidad('saborResidual', 'afectiva', v)"
|
||||
/>
|
||||
</div>
|
||||
@@ -111,18 +119,20 @@
|
||||
|
||||
<!-- Sliders de Acidez -->
|
||||
<div class="form-section">
|
||||
<h5 class="form-section-title cata-text">Acidez</h5>
|
||||
<h5 class="form-section-title cata-text" :style="{ color: getCategoryColor('acidez') }">Acidez</h5>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<CataSliderIntensidad
|
||||
tipo="descriptiva"
|
||||
label="Descriptiva"
|
||||
:model-value="muestra.intensidades.acidez.descriptiva"
|
||||
:color="getCategoryColor('acidez')"
|
||||
@update:model-value="(v) => actualizarIntensidad('acidez', 'descriptiva', v)"
|
||||
/>
|
||||
<CataSliderIntensidad
|
||||
tipo="afectiva"
|
||||
label="Afectiva"
|
||||
:model-value="muestra.intensidades.acidez.afectiva"
|
||||
:color="getCategoryColor('acidez')"
|
||||
@update:model-value="(v) => actualizarIntensidad('acidez', 'afectiva', v)"
|
||||
/>
|
||||
</div>
|
||||
@@ -130,18 +140,20 @@
|
||||
|
||||
<!-- Sliders de Dulzor -->
|
||||
<div class="form-section">
|
||||
<h5 class="form-section-title cata-text">Dulzor</h5>
|
||||
<h5 class="form-section-title cata-text" :style="{ color: getCategoryColor('dulzor') }">Dulzor</h5>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<CataSliderIntensidad
|
||||
tipo="descriptiva"
|
||||
label="Descriptiva"
|
||||
:model-value="muestra.intensidades.dulzor.descriptiva"
|
||||
:color="getCategoryColor('dulzor')"
|
||||
@update:model-value="(v) => actualizarIntensidad('dulzor', 'descriptiva', v)"
|
||||
/>
|
||||
<CataSliderIntensidad
|
||||
tipo="afectiva"
|
||||
label="Afectiva"
|
||||
:model-value="muestra.intensidades.dulzor.afectiva"
|
||||
:color="getCategoryColor('dulzor')"
|
||||
@update:model-value="(v) => actualizarIntensidad('dulzor', 'afectiva', v)"
|
||||
/>
|
||||
</div>
|
||||
@@ -149,18 +161,20 @@
|
||||
|
||||
<!-- Sliders de Sensación en Boca -->
|
||||
<div class="form-section">
|
||||
<h5 class="form-section-title cata-text">Sensación en la Boca</h5>
|
||||
<h5 class="form-section-title cata-text" :style="{ color: getCategoryColor('sensacionBoca') }">Sensación en la Boca</h5>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<CataSliderIntensidad
|
||||
tipo="descriptiva"
|
||||
label="Descriptiva"
|
||||
:model-value="muestra.intensidades.sensacionBoca.descriptiva"
|
||||
:color="getCategoryColor('sensacionBoca')"
|
||||
@update:model-value="(v) => actualizarIntensidad('sensacionBoca', 'descriptiva', v)"
|
||||
/>
|
||||
<CataSliderIntensidad
|
||||
tipo="afectiva"
|
||||
label="Afectiva"
|
||||
:model-value="muestra.intensidades.sensacionBoca.afectiva"
|
||||
:color="getCategoryColor('sensacionBoca')"
|
||||
@update:model-value="(v) => actualizarIntensidad('sensacionBoca', 'afectiva', v)"
|
||||
/>
|
||||
</div>
|
||||
@@ -168,18 +182,20 @@
|
||||
|
||||
<!-- Sliders de Impresión Global -->
|
||||
<div class="form-section">
|
||||
<h5 class="form-section-title cata-text">Impresión Global</h5>
|
||||
<h5 class="form-section-title cata-text" :style="{ color: getCategoryColor('impresionGlobal') }">Impresión Global</h5>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<CataSliderIntensidad
|
||||
tipo="descriptiva"
|
||||
label="Descriptiva"
|
||||
:model-value="muestra.intensidades.impresionGlobal.descriptiva"
|
||||
:color="getCategoryColor('impresionGlobal')"
|
||||
@update:model-value="(v) => actualizarIntensidad('impresionGlobal', 'descriptiva', v)"
|
||||
/>
|
||||
<CataSliderIntensidad
|
||||
tipo="afectiva"
|
||||
label="Afectiva"
|
||||
:model-value="muestra.intensidades.impresionGlobal.afectiva"
|
||||
:color="getCategoryColor('impresionGlobal')"
|
||||
@update:model-value="(v) => actualizarIntensidad('impresionGlobal', 'afectiva', v)"
|
||||
/>
|
||||
</div>
|
||||
@@ -271,18 +287,20 @@
|
||||
|
||||
<!-- Fragancia -->
|
||||
<div class="form-section mb-4">
|
||||
<h6 class="form-subsection-title cata-text">Fragancia</h6>
|
||||
<h6 class="form-subsection-title cata-text" :style="{ color: getCategoryColor('fragancia') }">Fragancia</h6>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<CataSliderIntensidad
|
||||
tipo="descriptiva"
|
||||
label="Descriptiva"
|
||||
:model-value="muestra.intensidades.fragancia.descriptiva"
|
||||
:color="getCategoryColor('fragancia')"
|
||||
@update:model-value="(v) => actualizarIntensidad('fragancia', 'descriptiva', v)"
|
||||
/>
|
||||
<CataSliderIntensidad
|
||||
tipo="afectiva"
|
||||
label="Afectiva"
|
||||
:model-value="muestra.intensidades.fragancia.afectiva"
|
||||
:color="getCategoryColor('fragancia')"
|
||||
@update:model-value="(v) => actualizarIntensidad('fragancia', 'afectiva', v)"
|
||||
/>
|
||||
</div>
|
||||
@@ -290,18 +308,20 @@
|
||||
|
||||
<!-- Aroma -->
|
||||
<div class="form-section mb-4">
|
||||
<h6 class="form-subsection-title cata-text">Aroma</h6>
|
||||
<h6 class="form-subsection-title cata-text" :style="{ color: getCategoryColor('aroma') }">Aroma</h6>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<CataSliderIntensidad
|
||||
tipo="descriptiva"
|
||||
label="Descriptiva"
|
||||
:model-value="muestra.intensidades.aroma.descriptiva"
|
||||
:color="getCategoryColor('aroma')"
|
||||
@update:model-value="(v) => actualizarIntensidad('aroma', 'descriptiva', v)"
|
||||
/>
|
||||
<CataSliderIntensidad
|
||||
tipo="afectiva"
|
||||
label="Afectiva"
|
||||
:model-value="muestra.intensidades.aroma.afectiva"
|
||||
:color="getCategoryColor('aroma')"
|
||||
@update:model-value="(v) => actualizarIntensidad('aroma', 'afectiva', v)"
|
||||
/>
|
||||
</div>
|
||||
@@ -309,18 +329,20 @@
|
||||
|
||||
<!-- Sabor -->
|
||||
<div class="form-section mb-4">
|
||||
<h6 class="form-subsection-title cata-text">Sabor</h6>
|
||||
<h6 class="form-subsection-title cata-text" :style="{ color: getCategoryColor('sabor') }">Sabor</h6>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<CataSliderIntensidad
|
||||
tipo="descriptiva"
|
||||
label="Descriptiva"
|
||||
:model-value="muestra.intensidades.sabor.descriptiva"
|
||||
:color="getCategoryColor('sabor')"
|
||||
@update:model-value="(v) => actualizarIntensidad('sabor', 'descriptiva', v)"
|
||||
/>
|
||||
<CataSliderIntensidad
|
||||
tipo="afectiva"
|
||||
label="Afectiva"
|
||||
:model-value="muestra.intensidades.sabor.afectiva"
|
||||
:color="getCategoryColor('sabor')"
|
||||
@update:model-value="(v) => actualizarIntensidad('sabor', 'afectiva', v)"
|
||||
/>
|
||||
</div>
|
||||
@@ -328,18 +350,20 @@
|
||||
|
||||
<!-- Sabor Residual -->
|
||||
<div class="form-section mb-4">
|
||||
<h6 class="form-subsection-title cata-text">Sabor Residual</h6>
|
||||
<h6 class="form-subsection-title cata-text" :style="{ color: getCategoryColor('saborResidual') }">Sabor Residual</h6>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<CataSliderIntensidad
|
||||
tipo="descriptiva"
|
||||
label="Descriptiva"
|
||||
:model-value="muestra.intensidades.saborResidual.descriptiva"
|
||||
:color="getCategoryColor('saborResidual')"
|
||||
@update:model-value="(v) => actualizarIntensidad('saborResidual', 'descriptiva', v)"
|
||||
/>
|
||||
<CataSliderIntensidad
|
||||
tipo="afectiva"
|
||||
label="Afectiva"
|
||||
:model-value="muestra.intensidades.saborResidual.afectiva"
|
||||
:color="getCategoryColor('saborResidual')"
|
||||
@update:model-value="(v) => actualizarIntensidad('saborResidual', 'afectiva', v)"
|
||||
/>
|
||||
</div>
|
||||
@@ -347,18 +371,20 @@
|
||||
|
||||
<!-- Acidez -->
|
||||
<div class="form-section mb-4">
|
||||
<h6 class="form-subsection-title cata-text">Acidez</h6>
|
||||
<h6 class="form-subsection-title cata-text" :style="{ color: getCategoryColor('acidez') }">Acidez</h6>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<CataSliderIntensidad
|
||||
tipo="descriptiva"
|
||||
label="Descriptiva"
|
||||
:model-value="muestra.intensidades.acidez.descriptiva"
|
||||
:color="getCategoryColor('acidez')"
|
||||
@update:model-value="(v) => actualizarIntensidad('acidez', 'descriptiva', v)"
|
||||
/>
|
||||
<CataSliderIntensidad
|
||||
tipo="afectiva"
|
||||
label="Afectiva"
|
||||
:model-value="muestra.intensidades.acidez.afectiva"
|
||||
:color="getCategoryColor('acidez')"
|
||||
@update:model-value="(v) => actualizarIntensidad('acidez', 'afectiva', v)"
|
||||
/>
|
||||
</div>
|
||||
@@ -366,18 +392,20 @@
|
||||
|
||||
<!-- Dulzor -->
|
||||
<div class="form-section mb-4">
|
||||
<h6 class="form-subsection-title cata-text">Dulzor</h6>
|
||||
<h6 class="form-subsection-title cata-text" :style="{ color: getCategoryColor('dulzor') }">Dulzor</h6>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<CataSliderIntensidad
|
||||
tipo="descriptiva"
|
||||
label="Descriptiva"
|
||||
:model-value="muestra.intensidades.dulzor.descriptiva"
|
||||
:color="getCategoryColor('dulzor')"
|
||||
@update:model-value="(v) => actualizarIntensidad('dulzor', 'descriptiva', v)"
|
||||
/>
|
||||
<CataSliderIntensidad
|
||||
tipo="afectiva"
|
||||
label="Afectiva"
|
||||
:model-value="muestra.intensidades.dulzor.afectiva"
|
||||
:color="getCategoryColor('dulzor')"
|
||||
@update:model-value="(v) => actualizarIntensidad('dulzor', 'afectiva', v)"
|
||||
/>
|
||||
</div>
|
||||
@@ -385,18 +413,20 @@
|
||||
|
||||
<!-- Sensación en Boca -->
|
||||
<div class="form-section mb-4">
|
||||
<h6 class="form-subsection-title cata-text">Sensación en la Boca</h6>
|
||||
<h6 class="form-subsection-title cata-text" :style="{ color: getCategoryColor('sensacionBoca') }">Sensación en la Boca</h6>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<CataSliderIntensidad
|
||||
tipo="descriptiva"
|
||||
label="Descriptiva"
|
||||
:model-value="muestra.intensidades.sensacionBoca.descriptiva"
|
||||
:color="getCategoryColor('sensacionBoca')"
|
||||
@update:model-value="(v) => actualizarIntensidad('sensacionBoca', 'descriptiva', v)"
|
||||
/>
|
||||
<CataSliderIntensidad
|
||||
tipo="afectiva"
|
||||
label="Afectiva"
|
||||
:model-value="muestra.intensidades.sensacionBoca.afectiva"
|
||||
:color="getCategoryColor('sensacionBoca')"
|
||||
@update:model-value="(v) => actualizarIntensidad('sensacionBoca', 'afectiva', v)"
|
||||
/>
|
||||
</div>
|
||||
@@ -404,18 +434,20 @@
|
||||
|
||||
<!-- Impresión Global -->
|
||||
<div class="form-section">
|
||||
<h6 class="form-subsection-title cata-text">Impresión Global</h6>
|
||||
<h6 class="form-subsection-title cata-text" :style="{ color: getCategoryColor('impresionGlobal') }">Impresión Global</h6>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<CataSliderIntensidad
|
||||
tipo="descriptiva"
|
||||
label="Descriptiva"
|
||||
:model-value="muestra.intensidades.impresionGlobal.descriptiva"
|
||||
:color="getCategoryColor('impresionGlobal')"
|
||||
@update:model-value="(v) => actualizarIntensidad('impresionGlobal', 'descriptiva', v)"
|
||||
/>
|
||||
<CataSliderIntensidad
|
||||
tipo="afectiva"
|
||||
label="Afectiva"
|
||||
:model-value="muestra.intensidades.impresionGlobal.afectiva"
|
||||
:color="getCategoryColor('impresionGlobal')"
|
||||
@update:model-value="(v) => actualizarIntensidad('impresionGlobal', 'afectiva', v)"
|
||||
/>
|
||||
</div>
|
||||
@@ -560,6 +592,7 @@ interface FormularioMuestraProps {
|
||||
const props = defineProps<FormularioMuestraProps>()
|
||||
|
||||
const { actualizarIntensidad: actualizarIntensidadCatacion } = useCatacion()
|
||||
const { getCategoryColor } = useCategoryColors()
|
||||
|
||||
// Listas para los selectores
|
||||
const sensacionesBoca = SENSACIONES_BOCA
|
||||
@@ -693,16 +726,14 @@ watch(() => props.muestra.otrasNotas, (newVal) => {
|
||||
|
||||
.form-section-title {
|
||||
font-size: 0.875rem;
|
||||
font-weight: 600;
|
||||
font-weight: 700;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
opacity: 0.75;
|
||||
}
|
||||
|
||||
.form-subsection-title {
|
||||
font-size: 0.8125rem;
|
||||
font-weight: 600;
|
||||
opacity: 0.7;
|
||||
font-weight: 700;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="slider-intensidad cata-fade-in">
|
||||
<div class="slider-intensidad cata-fade-in" :style="customColorStyle">
|
||||
<!-- Label -->
|
||||
<label
|
||||
v-if="label"
|
||||
@@ -59,12 +59,14 @@ interface SliderIntensidadProps {
|
||||
required?: boolean
|
||||
/** Mostrar descripción del tipo */
|
||||
showDescription?: boolean
|
||||
/** Color personalizado para el slider */
|
||||
color?: string
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<SliderIntensidadProps>(), {
|
||||
disabled: false,
|
||||
required: false,
|
||||
showDescription: true,
|
||||
showDescription: false,
|
||||
})
|
||||
|
||||
const emit = defineEmits<{
|
||||
@@ -95,11 +97,11 @@ const tooltipConfig = computed<boolean | TooltipProps>(() => ({
|
||||
// Configuración UI personalizada del slider
|
||||
const sliderUi = computed(() => ({
|
||||
root: 'cata-slider-root',
|
||||
track: 'cata-slider-track',
|
||||
track: `cata-slider-track ${props.color ? 'cata-slider-track-custom' : ''}`,
|
||||
range: props.tipo === 'descriptiva'
|
||||
? 'bg-primary/20 dark:bg-primary/30'
|
||||
: 'bg-primary/40 dark:bg-primary/50',
|
||||
thumb: 'cata-slider-thumb',
|
||||
thumb: `cata-slider-thumb ${props.color ? 'cata-slider-thumb-custom' : ''}`,
|
||||
}))
|
||||
|
||||
// Manejar cambio de valor
|
||||
@@ -111,6 +113,14 @@ const handleChange = (value: number | number[] | undefined) => {
|
||||
const newValue = Array.isArray(value) ? (value[0] ?? null) : value
|
||||
emit('update:modelValue', newValue)
|
||||
}
|
||||
|
||||
// Estilo dinámico para el color personalizado
|
||||
const customColorStyle = computed(() => {
|
||||
if (!props.color) return {}
|
||||
return {
|
||||
'--slider-custom-color': props.color,
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
@@ -132,6 +142,10 @@ const handleChange = (value: number | number[] | undefined) => {
|
||||
border-color: color-mix(in srgb, var(--cata-primary) 50%, transparent);
|
||||
}
|
||||
|
||||
:deep(.cata-slider-track-custom) {
|
||||
border-color: color-mix(in srgb, var(--slider-custom-color) 50%, transparent);
|
||||
}
|
||||
|
||||
:deep(.cata-slider-thumb) {
|
||||
width: 1.25rem;
|
||||
height: 1.25rem;
|
||||
@@ -142,6 +156,10 @@ const handleChange = (value: number | number[] | undefined) => {
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
:deep(.cata-slider-thumb-custom) {
|
||||
border-color: var(--slider-custom-color);
|
||||
}
|
||||
|
||||
:deep(.cata-slider-thumb:hover) {
|
||||
transform: scale(1.1);
|
||||
box-shadow: 0 3px 6px rgba(0, 0, 0, 0.15);
|
||||
@@ -155,10 +173,18 @@ const handleChange = (value: number | number[] | undefined) => {
|
||||
box-shadow: 0 0 6px var(--cata-primary);
|
||||
}
|
||||
|
||||
.dark :deep(.cata-slider-thumb-custom) {
|
||||
box-shadow: 0 0 6px var(--slider-custom-color);
|
||||
}
|
||||
|
||||
.dark :deep(.cata-slider-thumb:hover) {
|
||||
box-shadow: 0 0 12px var(--cata-primary);
|
||||
}
|
||||
|
||||
.dark :deep(.cata-slider-thumb-custom:hover) {
|
||||
box-shadow: 0 0 12px var(--slider-custom-color);
|
||||
}
|
||||
|
||||
/* Animación de fade in */
|
||||
.slider-intensidad.cata-fade-in {
|
||||
animation: cata-fade-in 0.3s ease-out;
|
||||
|
||||
81
nuxt4/app/composables/useCategoryColors.ts
Normal file
81
nuxt4/app/composables/useCategoryColors.ts
Normal file
@@ -0,0 +1,81 @@
|
||||
/**
|
||||
* Composable para gestionar colores de categorías de intensidades
|
||||
* Define una paleta de 8 colores coordinados (con variantes light/dark)
|
||||
*/
|
||||
|
||||
export type CategoriaIntensidad =
|
||||
| 'fragancia'
|
||||
| 'aroma'
|
||||
| 'sabor'
|
||||
| 'saborResidual'
|
||||
| 'acidez'
|
||||
| 'dulzor'
|
||||
| 'sensacionBoca'
|
||||
| 'impresionGlobal'
|
||||
|
||||
interface ColorPalette {
|
||||
light: string
|
||||
dark: string
|
||||
}
|
||||
|
||||
// Paleta de colores coordinados para cada categoría
|
||||
const CATEGORY_COLORS: Record<CategoriaIntensidad, ColorPalette> = {
|
||||
fragancia: {
|
||||
light: '#8B7AB8', // Lavanda
|
||||
dark: '#B39DDB',
|
||||
},
|
||||
aroma: {
|
||||
light: '#26A69A', // Verde Menta
|
||||
dark: '#4DB6AC',
|
||||
},
|
||||
sabor: {
|
||||
light: '#E53935', // Rojo Carmesí
|
||||
dark: '#EF5350',
|
||||
},
|
||||
saborResidual: {
|
||||
light: '#F57C00', // Naranja
|
||||
dark: '#FF9800',
|
||||
},
|
||||
acidez: {
|
||||
light: '#FDD835', // Amarillo Limón
|
||||
dark: '#FFEB3B',
|
||||
},
|
||||
dulzor: {
|
||||
light: '#EC407A', // Rosa Magenta
|
||||
dark: '#F06292',
|
||||
},
|
||||
sensacionBoca: {
|
||||
light: '#1E88E5', // Azul
|
||||
dark: '#42A5F5',
|
||||
},
|
||||
impresionGlobal: {
|
||||
light: '#00ACC1', // Turquesa
|
||||
dark: '#26C6DA',
|
||||
},
|
||||
}
|
||||
|
||||
export const useCategoryColors = () => {
|
||||
const colorMode = useColorMode()
|
||||
const isDark = computed(() => colorMode.value === 'dark')
|
||||
|
||||
/**
|
||||
* Obtiene el color de una categoría según el tema actual
|
||||
*/
|
||||
const getCategoryColor = (category: CategoriaIntensidad): string => {
|
||||
return isDark.value
|
||||
? CATEGORY_COLORS[category].dark
|
||||
: CATEGORY_COLORS[category].light
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtiene ambas variantes de color de una categoría
|
||||
*/
|
||||
const getCategoryColorPalette = (category: CategoriaIntensidad): ColorPalette => {
|
||||
return CATEGORY_COLORS[category]
|
||||
}
|
||||
|
||||
return {
|
||||
getCategoryColor,
|
||||
getCategoryColorPalette,
|
||||
}
|
||||
}
|
||||
@@ -112,39 +112,65 @@ function hslToHex(h: number, s: number, l: number): string {
|
||||
}
|
||||
|
||||
/**
|
||||
* Aplica el color personalizado a las variables CSS
|
||||
* Aplica los colores personalizados a las variables CSS
|
||||
*/
|
||||
function applyCustomColor(color: string, isDark: boolean) {
|
||||
function applyCustomColors(primary?: string, foreground?: string, background?: string) {
|
||||
if (import.meta.server) return
|
||||
|
||||
const hsl = hexToHSL(color)
|
||||
// Aplicar color principal si se proporciona
|
||||
if (primary) {
|
||||
const hsl = hexToHSL(primary)
|
||||
|
||||
// Aplicar color principal en formato HEX
|
||||
document.documentElement.style.setProperty('--cata-primary', color)
|
||||
document.documentElement.style.setProperty('--cata-primary', primary)
|
||||
|
||||
// Generar variantes light y dark
|
||||
const lightHsl = { ...hsl, l: Math.min(hsl.l + 15, 95) }
|
||||
const darkHsl = { ...hsl, l: Math.max(hsl.l - 15, 10) }
|
||||
// Generar variantes light y dark
|
||||
const lightHsl = { ...hsl, l: Math.min(hsl.l + 15, 95) }
|
||||
const darkHsl = { ...hsl, l: Math.max(hsl.l - 15, 10) }
|
||||
|
||||
const lightColor = hslToHex(lightHsl.h, lightHsl.s, lightHsl.l)
|
||||
const darkColor = hslToHex(darkHsl.h, darkHsl.s, darkHsl.l)
|
||||
const lightColor = hslToHex(lightHsl.h, lightHsl.s, lightHsl.l)
|
||||
const darkColor = hslToHex(darkHsl.h, darkHsl.s, darkHsl.l)
|
||||
|
||||
document.documentElement.style.setProperty('--cata-primary-light', lightColor)
|
||||
document.documentElement.style.setProperty('--cata-primary-dark', darkColor)
|
||||
document.documentElement.style.setProperty('--cata-primary-light', lightColor)
|
||||
document.documentElement.style.setProperty('--cata-primary-dark', darkColor)
|
||||
|
||||
// Aplicar paleta completa para Nuxt UI (en formato HSL)
|
||||
const palette = generateColorPalette(color)
|
||||
Object.entries(palette).forEach(([key, value]) => {
|
||||
document.documentElement.style.setProperty(`--color-primary-${key}`, value)
|
||||
})
|
||||
// Aplicar paleta completa para Nuxt UI (en formato HSL)
|
||||
const palette = generateColorPalette(primary)
|
||||
Object.entries(palette).forEach(([key, value]) => {
|
||||
document.documentElement.style.setProperty(`--color-primary-${key}`, value)
|
||||
})
|
||||
}
|
||||
|
||||
// Aplicar color de fuente si se proporciona
|
||||
if (foreground) {
|
||||
document.documentElement.style.setProperty('--cata-fg', foreground)
|
||||
}
|
||||
|
||||
// Aplicar color de background si se proporciona
|
||||
if (background) {
|
||||
document.documentElement.style.setProperty('--cata-bg', background)
|
||||
}
|
||||
}
|
||||
|
||||
interface ThemeColors {
|
||||
primary: string | null
|
||||
foreground: string | null
|
||||
background: string | null
|
||||
}
|
||||
|
||||
/**
|
||||
* Colores por defecto según el tema
|
||||
*/
|
||||
const DEFAULT_COLORS = {
|
||||
light: '#4682B4', // SteelBlue
|
||||
dark: '#00FF00', // Verde terminal
|
||||
light: {
|
||||
primary: '#4682B4',
|
||||
foreground: '#000000',
|
||||
background: '#ffffff',
|
||||
},
|
||||
dark: {
|
||||
primary: '#00FF00',
|
||||
foreground: '#00FF00',
|
||||
background: '#000000',
|
||||
},
|
||||
}
|
||||
|
||||
const STORAGE_KEY = 'riocata-custom-colors'
|
||||
@@ -153,10 +179,13 @@ export const useColorCustomization = () => {
|
||||
const colorMode = useColorMode()
|
||||
const isDark = computed(() => colorMode.value === 'dark')
|
||||
|
||||
// Estado reactivo del color personalizado
|
||||
const customColors = useState<{ light: string | null; dark: string | null }>(
|
||||
// Estado reactivo de los colores personalizados
|
||||
const customColors = useState<{ light: ThemeColors; dark: ThemeColors }>(
|
||||
'custom-colors',
|
||||
() => ({ light: null, dark: null })
|
||||
() => ({
|
||||
light: { primary: null, foreground: null, background: null },
|
||||
dark: { primary: null, foreground: null, background: null },
|
||||
})
|
||||
)
|
||||
|
||||
/**
|
||||
@@ -190,31 +219,37 @@ export const useColorCustomization = () => {
|
||||
}
|
||||
|
||||
/**
|
||||
* Establece un color personalizado para el tema actual
|
||||
* Establece colores personalizados para el tema actual
|
||||
*/
|
||||
const setCustomColor = (color: string) => {
|
||||
const setCustomColors = (primary?: string, foreground?: string, background?: string) => {
|
||||
if (import.meta.server) return
|
||||
|
||||
const theme = isDark.value ? 'dark' : 'light'
|
||||
customColors.value[theme] = color
|
||||
|
||||
if (primary !== undefined) customColors.value[theme].primary = primary
|
||||
if (foreground !== undefined) customColors.value[theme].foreground = foreground
|
||||
if (background !== undefined) customColors.value[theme].background = background
|
||||
|
||||
saveCustomColors()
|
||||
applyCustomColor(color, isDark.value)
|
||||
applyCustomColors(primary, foreground, background)
|
||||
}
|
||||
|
||||
/**
|
||||
* Resetea el color al valor por defecto del tema actual
|
||||
* Resetea los colores al valor por defecto del tema actual
|
||||
*/
|
||||
const resetColor = () => {
|
||||
const resetColors = () => {
|
||||
if (import.meta.server) return
|
||||
|
||||
const theme = isDark.value ? 'dark' : 'light'
|
||||
customColors.value[theme] = null
|
||||
customColors.value[theme] = { primary: null, foreground: null, background: null }
|
||||
saveCustomColors()
|
||||
|
||||
// Limpiar las variables CSS personalizadas para que vuelvan a los valores del CSS
|
||||
document.documentElement.style.removeProperty('--cata-primary')
|
||||
document.documentElement.style.removeProperty('--cata-primary-light')
|
||||
document.documentElement.style.removeProperty('--cata-primary-dark')
|
||||
document.documentElement.style.removeProperty('--cata-fg')
|
||||
document.documentElement.style.removeProperty('--cata-bg')
|
||||
|
||||
// Limpiar paleta de Nuxt UI
|
||||
for (let i = 50; i <= 950; i += (i < 100 ? 50 : 100)) {
|
||||
@@ -223,19 +258,24 @@ export const useColorCustomization = () => {
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtiene el color actual (personalizado o por defecto)
|
||||
* Obtiene los colores actuales (personalizados o por defecto)
|
||||
*/
|
||||
const getCurrentColor = computed(() => {
|
||||
const getCurrentColors = computed(() => {
|
||||
const theme = isDark.value ? 'dark' : 'light'
|
||||
return customColors.value[theme] || DEFAULT_COLORS[theme]
|
||||
return {
|
||||
primary: customColors.value[theme].primary || DEFAULT_COLORS[theme].primary,
|
||||
foreground: customColors.value[theme].foreground || DEFAULT_COLORS[theme].foreground,
|
||||
background: customColors.value[theme].background || DEFAULT_COLORS[theme].background,
|
||||
}
|
||||
})
|
||||
|
||||
/**
|
||||
* Verifica si hay un color personalizado para el tema actual
|
||||
* Verifica si hay colores personalizados para el tema actual
|
||||
*/
|
||||
const hasCustomColor = computed(() => {
|
||||
const hasCustomColors = computed(() => {
|
||||
const theme = isDark.value ? 'dark' : 'light'
|
||||
return customColors.value[theme] !== null
|
||||
const colors = customColors.value[theme]
|
||||
return colors.primary !== null || colors.foreground !== null || colors.background !== null
|
||||
})
|
||||
|
||||
/**
|
||||
@@ -248,26 +288,36 @@ export const useColorCustomization = () => {
|
||||
|
||||
// Solo aplicar colores si hay colores personalizados guardados
|
||||
const theme = isDark.value ? 'dark' : 'light'
|
||||
if (customColors.value[theme]) {
|
||||
applyCustomColor(customColors.value[theme], isDark.value)
|
||||
const colors = customColors.value[theme]
|
||||
if (colors.primary || colors.foreground || colors.background) {
|
||||
applyCustomColors(
|
||||
colors.primary || undefined,
|
||||
colors.foreground || undefined,
|
||||
colors.background || undefined
|
||||
)
|
||||
}
|
||||
|
||||
// Observar cambios en el modo de color
|
||||
watch(isDark, (newIsDark) => {
|
||||
const theme = newIsDark ? 'dark' : 'light'
|
||||
// Solo aplicar si hay color personalizado para este tema
|
||||
if (customColors.value[theme]) {
|
||||
applyCustomColor(customColors.value[theme], newIsDark)
|
||||
const colors = customColors.value[theme]
|
||||
// Solo aplicar si hay colores personalizados para este tema
|
||||
if (colors.primary || colors.foreground || colors.background) {
|
||||
applyCustomColors(
|
||||
colors.primary || undefined,
|
||||
colors.foreground || undefined,
|
||||
colors.background || undefined
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
customColors: readonly(customColors),
|
||||
getCurrentColor,
|
||||
hasCustomColor,
|
||||
setCustomColor,
|
||||
resetColor,
|
||||
getCurrentColors,
|
||||
hasCustomColors,
|
||||
setCustomColors,
|
||||
resetColors,
|
||||
inicializar,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user