Add floating AI button with skills menu

Added always-on floating 'uncloseai.' button in bottom right corner that provides quick access to all AI skills: Chat, Read Page, TTS Anything, Upload File, and Refresh Models. Button uses ChunkFive font and gradient styling with smooth animations.
This commit is contained in:
Russell Ballestrini 2025-06-29 18:36:44 -04:00
parent 84a90f4dc2
commit af67a7be99

View file

@ -1029,11 +1029,128 @@ document.getElementById("user-input").addEventListener("keydown", function(event
});
// Function to create floating AI button
function createFloatingAIButton() {
// Create the main floating button
const floatingButton = document.createElement('button');
floatingButton.id = 'floating-ai-button';
floatingButton.textContent = 'uncloseai.';
floatingButton.style.cssText = `
position: fixed;
bottom: 20px;
right: 20px;
width: 80px;
height: 60px;
border-radius: 30px;
background: linear-gradient(45deg, #667eea 0%, #764ba2 100%);
border: none;
color: white;
font-family: 'ChunkFiveRegular', monospace;
font-size: 14px;
cursor: pointer;
box-shadow: 0 4px 12px rgba(0,0,0,0.3);
z-index: 1000;
transition: all 0.3s ease;
`;
// Create the skills menu
const skillsMenu = document.createElement('div');
skillsMenu.id = 'ai-skills-menu';
skillsMenu.style.cssText = `
position: fixed;
bottom: 90px;
right: 20px;
background: white;
border-radius: 12px;
box-shadow: 0 8px 24px rgba(0,0,0,0.2);
padding: 16px;
min-width: 200px;
z-index: 999;
display: none;
border: 1px solid #e0e0e0;
`;
// Skills buttons
const skills = [
{ name: 'Chat', icon: '💬', action: () => scrollToChatBox() },
{ name: 'Read Page', icon: '📖', action: readPageWithHermes },
{ name: 'TTS Anything', icon: '🔊', action: openTTSModal },
{ name: 'Upload File', icon: '📁', action: () => document.getElementById('file-input')?.click() },
{ name: 'Refresh Models', icon: '🔄', action: () => document.querySelector('#refresh-models-container button')?.click() }
];
skills.forEach(skill => {
const skillButton = document.createElement('button');
skillButton.style.cssText = `
display: flex;
align-items: center;
gap: 12px;
width: 100%;
padding: 12px;
margin: 4px 0;
border: none;
background: transparent;
border-radius: 8px;
cursor: pointer;
font-size: 14px;
transition: background-color 0.2s ease;
`;
skillButton.innerHTML = `<span style="font-size: 18px;">${skill.icon}</span> ${skill.name}`;
skillButton.onmouseover = () => skillButton.style.background = '#f5f5f5';
skillButton.onmouseout = () => skillButton.style.background = 'transparent';
skillButton.onclick = () => {
skill.action();
skillsMenu.style.display = 'none';
};
skillsMenu.appendChild(skillButton);
});
// Toggle menu visibility
let menuVisible = false;
floatingButton.onclick = () => {
menuVisible = !menuVisible;
skillsMenu.style.display = menuVisible ? 'block' : 'none';
floatingButton.style.transform = menuVisible ? 'rotate(180deg)' : 'rotate(0deg)';
};
// Close menu when clicking outside
document.addEventListener('click', (e) => {
if (!floatingButton.contains(e.target) && !skillsMenu.contains(e.target)) {
skillsMenu.style.display = 'none';
menuVisible = false;
floatingButton.style.transform = 'rotate(0deg)';
}
});
// Hover effects
floatingButton.onmouseenter = () => {
floatingButton.style.transform = 'scale(1.1)';
floatingButton.style.boxShadow = '0 6px 16px rgba(0,0,0,0.4)';
};
floatingButton.onmouseleave = () => {
if (!menuVisible) floatingButton.style.transform = 'scale(1)';
floatingButton.style.boxShadow = '0 4px 12px rgba(0,0,0,0.3)';
};
document.body.appendChild(floatingButton);
document.body.appendChild(skillsMenu);
}
// Helper function to scroll to chat box
function scrollToChatBox() {
const chatContainer = document.getElementById('chat-container');
if (chatContainer) {
chatContainer.scrollIntoView({ behavior: 'smooth' });
document.getElementById('user-input')?.focus();
}
}
// Initialize on page load
window.onload = () => {
initializeChatInterface();
createModelSelectionDropdown();
addRefreshModelsButton();
createFloatingAIButton();
};
// Export functions to global scope