Merge pull request #23 from josedario87/feat/chat-color-customization
Feat/chat color customization
This commit is contained in:
@@ -1,11 +1,24 @@
|
||||
<script setup>
|
||||
import { ref, nextTick, onMounted, watch } from 'vue'
|
||||
import { ref, nextTick, onMounted, watch, computed } from 'vue'
|
||||
import { useChat } from '@/stores/useChat'
|
||||
import { useUi } from '@/stores/useUi'
|
||||
|
||||
const chat = useChat()
|
||||
const ui = useUi()
|
||||
const msg = ref('')
|
||||
const list = ref(null)
|
||||
|
||||
const chatStyleVariables = computed(() => ({
|
||||
'--chat-agent-message-color': ui.chatAgentMessageColor,
|
||||
'--chat-own-message-color': ui.chatOwnMessageColor,
|
||||
'--chat-input-box-color': ui.chatInputBoxColor,
|
||||
'--chat-accent-color': ui.chatAccentColor,
|
||||
'--chat-background-color': ui.chatBackgroundColor,
|
||||
'--chat-font-color': ui.chatFontColor,
|
||||
'--chat-font-family': ui.chatFontFamily || 'inherit', // Fallback to inherit if empty
|
||||
'--chat-font-size': ui.chatFontSize ? `${ui.chatFontSize}px` : 'inherit', // Fallback to inherit
|
||||
}))
|
||||
|
||||
function scrollBottom () {
|
||||
nextTick(() => list.value?.scrollTo({ top: list.value.scrollHeight, behavior: 'smooth' }))
|
||||
}
|
||||
@@ -40,16 +53,22 @@ watch(() => chat.items.length, scrollBottom)
|
||||
|
||||
<template>
|
||||
<!-- se adapta al contenedor flex, sin superponer la sidebar -->
|
||||
<div class="flex flex-col flex-1 min-h-0 bg-gray-50">
|
||||
<div class="flex flex-col flex-1 min-h-0" :style="chatStyleVariables" style="background-color: var(--chat-background-color);">
|
||||
<!-- historial -->
|
||||
<div ref="list" class="flex-1 min-h-0 overflow-auto p-6 space-y-4 custom-scroll">
|
||||
<template v-for="(m,i) in chat.items" :key="i">
|
||||
<!-- mensaje de texto -->
|
||||
<div :class="m.owner==='yo' ? 'flex justify-end' : 'flex justify-start'" v-if="m.type==='text'">
|
||||
<div
|
||||
class="max-w-lg px-4 py-2 shadow break-words rounded-lg"
|
||||
:class="m.owner==='yo' ? 'text-white' : 'bg-white text-gray-900 dark:bg-gray-700 dark:text-gray-200'"
|
||||
:style="m.owner==='yo' ? { backgroundColor: 'var(--accent-color-chat, #0D9488)' } : {}">
|
||||
class="max-w-lg rounded-lg px-4 py-2 shadow break-words"
|
||||
:class="m.owner === 'yo' ? '' : ''"
|
||||
:style="{
|
||||
backgroundColor: m.owner === 'yo' ? 'var(--chat-own-message-color)' : 'var(--chat-agent-message-color)',
|
||||
color: 'var(--chat-font-color)',
|
||||
fontFamily: 'var(--chat-font-family)',
|
||||
fontSize: 'var(--chat-font-size)'
|
||||
}">
|
||||
|
||||
{{ m.text }}
|
||||
</div>
|
||||
</div>
|
||||
@@ -60,18 +79,24 @@ watch(() => chat.items.length, scrollBottom)
|
||||
</div>
|
||||
|
||||
<!-- input -->
|
||||
<form @submit.prevent="send" class="border-t bg-white p-4 flex gap-2">
|
||||
<form @submit.prevent="send" class="border-t p-4 flex gap-2" :style="{ backgroundColor: 'var(--chat-input-box-color)' }">
|
||||
<textarea
|
||||
v-model="msg"
|
||||
@keydown="handleKey"
|
||||
rows="1"
|
||||
placeholder="Escribí un mensaje… (Enter para enviar, Shift+Enter salto)"
|
||||
class="flex-1 resize-none rounded-md border border-gray-300 dark:border-gray-600 p-3 shadow-sm focus:outline-none focus:ring-2 focus:ring-[var(--accent-color-chat,#0D9488)] focus:border-[var(--accent-color-chat,#0D9488)] dark:bg-gray-700 dark:text-white custom-scroll"
|
||||
|
||||
class="flex-1 resize-none rounded-lg border p-3 focus:outline-none focus:ring-2 custom-scroll"
|
||||
:style="{
|
||||
backgroundColor: 'var(--chat-input-box-color)',
|
||||
borderColor: 'var(--chat-accent-color)',
|
||||
'--tw-ring-color': 'var(--chat-accent-color)',
|
||||
color: 'var(--chat-font-color)',
|
||||
fontFamily: 'var(--chat-font-family)',
|
||||
fontSize: 'var(--chat-font-size)'
|
||||
}"
|
||||
/>
|
||||
<button
|
||||
type="submit"
|
||||
class="px-4 py-2 rounded-md text-white transition-colors duration-150 ease-in-out shadow-sm hover:brightness-90"
|
||||
:style="{ backgroundColor: 'var(--accent-color-chat, #0D9488)' }">
|
||||
<button type="submit" class="px-4 py-2 rounded-lg text-white transition" :style="{ backgroundColor: 'var(--chat-accent-color)' }">
|
||||
➤
|
||||
</button>
|
||||
</form>
|
||||
@@ -92,16 +117,14 @@ watch(() => chat.items.length, scrollBottom)
|
||||
}
|
||||
|
||||
.custom-scroll::-webkit-scrollbar { width: 8px; }
|
||||
.custom-scroll::-webkit-scrollbar-track { background: transparent; }
|
||||
.custom-scroll::-webkit-scrollbar-thumb {
|
||||
background-color: var(--accent-color-chat-alpha-35, var(--accent-color-chat-alpha-35-fallback));
|
||||
border-radius: 4px;
|
||||
}
|
||||
.custom-scroll:hover::-webkit-scrollbar-thumb {
|
||||
background-color: var(--accent-color-chat-alpha-70, var(--accent-color-chat-alpha-70-fallback));
|
||||
}
|
||||
.custom-scroll {
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: var(--accent-color-chat-alpha-60, var(--accent-color-chat-alpha-60-fallback)) transparent;
|
||||
.custom-scroll::-webkit-scrollbar-track { background: transparent; } /* Consider if track needs to adapt to --chat-background-color */
|
||||
.custom-scroll::-webkit-scrollbar-thumb { background-color: var(--chat-accent-color); opacity: 0.35; border-radius: 4px; }
|
||||
.custom-scroll:hover::-webkit-scrollbar-thumb { opacity: 0.7; }
|
||||
/* For Firefox scrollbar, if needed, though limited styling capability compared to webkit */
|
||||
.custom-scroll { scrollbar-width: thin; scrollbar-color: var(--chat-accent-color) transparent; }
|
||||
|
||||
/* Override Tailwind focus ring color if it doesn't pick up the CSS variable directly */
|
||||
textarea:focus {
|
||||
--tw-ring-color: var(--chat-accent-color);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -32,7 +32,14 @@ const appearanceSettingKeys = [
|
||||
'defaultViewAsistencias',
|
||||
'defaultViewConfiguracion',
|
||||
'transitionSpeed',
|
||||
'backgroundColorChat',
|
||||
'chatAgentMessageColor',
|
||||
'chatOwnMessageColor',
|
||||
'chatInputBoxColor',
|
||||
'chatAccentColor',
|
||||
'chatBackgroundColor',
|
||||
'chatFontColor',
|
||||
'chatFontFamily',
|
||||
'chatFontSize',
|
||||
|
||||
]
|
||||
|
||||
@@ -111,6 +118,16 @@ export const useUi = defineStore('ui', {
|
||||
'defaultViewAsistencias': 'table',
|
||||
'defaultViewConfiguracion': 'table',
|
||||
transitionSpeed: 1, // Default to normal speed
|
||||
// Chat UI colors
|
||||
chatAgentMessageColor: '#FFFFFF',
|
||||
chatOwnMessageColor: '#D1E8FF',
|
||||
chatInputBoxColor: '#FFFFFF',
|
||||
chatAccentColor: '#1976D2',
|
||||
chatBackgroundColor: '#F4F4F4',
|
||||
// Chat UI fonts
|
||||
chatFontColor: '#000000',
|
||||
chatFontFamily: '',
|
||||
chatFontSize: 14,
|
||||
}
|
||||
|
||||
const loadedSettings = loadSettingsFromLocalStorage()
|
||||
@@ -259,6 +276,42 @@ export const useUi = defineStore('ui', {
|
||||
this.transitionSpeed = Number(newSpeed) // Ensure it's a number
|
||||
_saveAppearanceState(this)
|
||||
},
|
||||
|
||||
// Actions for chat UI colors
|
||||
setChatAgentMessageColor(color) {
|
||||
this.chatAgentMessageColor = color
|
||||
_saveAppearanceState(this)
|
||||
},
|
||||
setChatOwnMessageColor(color) {
|
||||
this.chatOwnMessageColor = color
|
||||
_saveAppearanceState(this)
|
||||
},
|
||||
setChatInputBoxColor(color) {
|
||||
this.chatInputBoxColor = color
|
||||
_saveAppearanceState(this)
|
||||
},
|
||||
setChatAccentColor(color) {
|
||||
this.chatAccentColor = color
|
||||
_saveAppearanceState(this)
|
||||
},
|
||||
setChatBackgroundColor(color) {
|
||||
this.chatBackgroundColor = color
|
||||
_saveAppearanceState(this)
|
||||
},
|
||||
|
||||
// Actions for chat UI fonts
|
||||
setChatFontColor(color) {
|
||||
this.chatFontColor = color
|
||||
_saveAppearanceState(this)
|
||||
},
|
||||
setChatFontFamily(font) {
|
||||
this.chatFontFamily = font
|
||||
_saveAppearanceState(this)
|
||||
},
|
||||
setChatFontSize(size) {
|
||||
this.chatFontSize = Number(size)
|
||||
_saveAppearanceState(this)
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
@@ -95,6 +95,61 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Chat Interface Colors Section -->
|
||||
<section class="mb-10">
|
||||
<h2 class="text-2xl font-semibold mb-6 text-[var(--primary-color)]">Chat Interface Colors</h2>
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-6">
|
||||
<div class="setting-item">
|
||||
<label for="chatAgentMessageColor" class="block text-sm font-medium mb-1">Agent Message Color</label>
|
||||
<input type="color" id="chatAgentMessageColor" v-model="ui.chatAgentMessageColor" @input="ui.setChatAgentMessageColor($event.target.value)"
|
||||
class="w-full h-12 p-1 border rounded-lg cursor-pointer shadow-sm hover:opacity-80 transition-opacity border-[var(--secondary-color)] focus:border-[var(--primary-color)] focus:ring-1 focus:ring-[var(--primary-color)]">
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<label for="chatOwnMessageColor" class="block text-sm font-medium mb-1">Own Message Color</label>
|
||||
<input type="color" id="chatOwnMessageColor" v-model="ui.chatOwnMessageColor" @input="ui.setChatOwnMessageColor($event.target.value)"
|
||||
class="w-full h-12 p-1 border rounded-lg cursor-pointer shadow-sm hover:opacity-80 transition-opacity border-[var(--secondary-color)] focus:border-[var(--primary-color)] focus:ring-1 focus:ring-[var(--primary-color)]">
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<label for="chatInputBoxColor" class="block text-sm font-medium mb-1">Input Box Color</label>
|
||||
<input type="color" id="chatInputBoxColor" v-model="ui.chatInputBoxColor" @input="ui.setChatInputBoxColor($event.target.value)"
|
||||
class="w-full h-12 p-1 border rounded-lg cursor-pointer shadow-sm hover:opacity-80 transition-opacity border-[var(--secondary-color)] focus:border-[var(--primary-color)] focus:ring-1 focus:ring-[var(--primary-color)]">
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<label for="chatAccentColor" class="block text-sm font-medium mb-1">Accent Color</label>
|
||||
<input type="color" id="chatAccentColor" v-model="ui.chatAccentColor" @input="ui.setChatAccentColor($event.target.value)"
|
||||
class="w-full h-12 p-1 border rounded-lg cursor-pointer shadow-sm hover:opacity-80 transition-opacity border-[var(--secondary-color)] focus:border-[var(--primary-color)] focus:ring-1 focus:ring-[var(--primary-color)]">
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<label for="chatBackgroundColor" class="block text-sm font-medium mb-1">Background Color</label>
|
||||
<input type="color" id="chatBackgroundColor" v-model="ui.chatBackgroundColor" @input="ui.setChatBackgroundColor($event.target.value)"
|
||||
class="w-full h-12 p-1 border rounded-lg cursor-pointer shadow-sm hover:opacity-80 transition-opacity border-[var(--secondary-color)] focus:border-[var(--primary-color)] focus:ring-1 focus:ring-[var(--primary-color)]">
|
||||
</div>
|
||||
|
||||
<!-- Chat Font Color -->
|
||||
<div class="setting-item">
|
||||
<label for="chatFontColor" class="block text-sm font-medium mb-1">Chat Font Color</label>
|
||||
<input type="color" id="chatFontColor" v-model="ui.chatFontColor" @input="ui.setChatFontColor($event.target.value)"
|
||||
class="w-full h-12 p-1 border rounded-lg cursor-pointer shadow-sm hover:opacity-80 transition-opacity border-[var(--secondary-color)] focus:border-[var(--primary-color)] focus:ring-1 focus:ring-[var(--primary-color)]">
|
||||
</div>
|
||||
|
||||
<!-- Chat Font Family -->
|
||||
<div class="setting-item">
|
||||
<label for="chatFontFamily" class="block text-sm font-medium mb-1">Chat Font Family</label>
|
||||
<input type="text" id="chatFontFamily" v-model="ui.chatFontFamily" @input="ui.setChatFontFamily($event.target.value)"
|
||||
class="w-full p-3 border rounded-lg shadow-sm focus:ring-[var(--primary-color)] focus:border-[var(--primary-color)] transition-all duration-150 ease-in-out bg-white/10 dark:bg-black/10 border-[var(--secondary-color)] hover:border-[var(--primary-color)]"
|
||||
placeholder="e.g., Arial, sans-serif">
|
||||
</div>
|
||||
|
||||
<!-- Chat Font Size -->
|
||||
<div class="setting-item">
|
||||
<label for="chatFontSize" class="block text-sm font-medium mb-1">Chat Font Size (px)</label>
|
||||
<input type="number" id="chatFontSize" v-model.number="ui.chatFontSize" @input="ui.setChatFontSize(Number($event.target.value))"
|
||||
class="w-full p-3 border rounded-lg shadow-sm focus:ring-[var(--primary-color)] focus:border-[var(--primary-color)] transition-all duration-150 ease-in-out bg-white/10 dark:bg-black/10 border-[var(--secondary-color)] hover:border-[var(--primary-color)]"
|
||||
min="8" max="32" step="1">
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Per-Module Color Settings -->
|
||||
<section class="mb-10 module-settings-group">
|
||||
<h3 class="text-xl font-semibold mb-4 text-[var(--primary-color)] border-b border-[var(--secondary-color)] pb-2">Empleados Module</h3>
|
||||
|
||||
Reference in New Issue
Block a user