feat: Add mobile-optimized FAB toggle button for panel

- Added floating action button (FAB) that appears only on mobile (≤768px)
- Panel becomes a bottom sheet modal on mobile instead of fixed sidebar
- Smooth slide-up animation with backdrop overlay
- Panel hidden by default on mobile, opens when FAB clicked
- Touch-friendly button sizes (44px minimum per Apple HIG)
- 70vh height on tablets, 80vh on phones for better usability
- Rounded top corners for modern mobile UI
- Desktop behavior unchanged
This commit is contained in:
Spicy_Marinara
2025-10-14 14:39:45 +02:00
parent 9609eef6ff
commit 7440860402
2 changed files with 177 additions and 0 deletions
+42
View File
@@ -302,6 +302,14 @@ async function initUI() {
// Append panel to body - positioning handled by CSS // Append panel to body - positioning handled by CSS
$('body').append(templateHtml); $('body').append(templateHtml);
// Add mobile toggle button (FAB - Floating Action Button)
const mobileToggleHtml = `
<button id="rpg-mobile-toggle" class="rpg-mobile-toggle" title="Toggle RPG Panel">
<i class="fa-solid fa-dice-d20"></i>
</button>
`;
$('body').append(mobileToggleHtml);
// Cache UI elements // Cache UI elements
$panelContainer = $('#rpg-companion-panel'); $panelContainer = $('#rpg-companion-panel');
$userStatsContainer = $('#rpg-user-stats'); $userStatsContainer = $('#rpg-user-stats');
@@ -478,6 +486,9 @@ async function initUI() {
toggleCustomColors(); toggleCustomColors();
toggleAnimations(); toggleAnimations();
// Setup mobile toggle button
setupMobileToggle();
// Render initial data if available // Render initial data if available
renderUserStats(); renderUserStats();
renderInfoBox(); renderInfoBox();
@@ -953,6 +964,37 @@ function setupSettingsPopup() {
}); });
} }
/**
* Sets up the mobile toggle button (FAB).
*/
function setupMobileToggle() {
const $mobileToggle = $('#rpg-mobile-toggle');
const $panel = $('#rpg-companion-panel');
const $overlay = $('<div class="rpg-mobile-overlay"></div>');
// Toggle panel visibility on mobile
$mobileToggle.on('click', function() {
if ($panel.hasClass('rpg-mobile-open')) {
// Close panel
$panel.removeClass('rpg-mobile-open');
$overlay.remove();
$mobileToggle.removeClass('active');
} else {
// Open panel
$panel.addClass('rpg-mobile-open');
$('body').append($overlay);
$mobileToggle.addClass('active');
// Close when clicking overlay
$overlay.on('click', function() {
$panel.removeClass('rpg-mobile-open');
$overlay.remove();
$mobileToggle.removeClass('active');
});
}
});
}
/** /**
* Updates the visibility of the entire panel. * Updates the visibility of the entire panel.
*/ */
+135
View File
@@ -2834,3 +2834,138 @@ body:has(.rpg-panel.rpg-position-left) #sheld {
} }
} }
/* ============================================
MOBILE TOGGLE BUTTON (FAB)
============================================ */
/* Hide mobile toggle on desktop, show on mobile */
.rpg-mobile-toggle {
display: none;
position: fixed;
bottom: 80px;
right: 20px;
width: 56px;
height: 56px;
border-radius: 50%;
background: var(--rpg-accent, #2c3e50);
border: 3px solid var(--rpg-border, #34495e);
color: var(--rpg-text, #ecf0f1);
font-size: 24px;
cursor: pointer;
z-index: 999;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
transition: all 0.3s ease;
}
.rpg-mobile-toggle:hover {
transform: scale(1.1);
box-shadow: 0 6px 16px rgba(0, 0, 0, 0.4);
}
.rpg-mobile-toggle:active {
transform: scale(0.95);
}
.rpg-mobile-toggle.active {
background: var(--rpg-highlight, #e74c3c);
transform: rotate(180deg);
}
/* Mobile overlay backdrop */
.rpg-mobile-overlay {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
z-index: 998;
backdrop-filter: blur(2px);
}
/* Mobile-specific panel behavior */
@media (max-width: 768px) {
/* Show the FAB on mobile */
.rpg-mobile-toggle {
display: flex;
align-items: center;
justify-content: center;
}
/* Show overlay when needed */
body:has(.rpg-panel.rpg-mobile-open) .rpg-mobile-overlay {
display: block;
}
/* Hide panel by default on mobile */
.rpg-panel {
transform: translateY(100%);
transition: transform 0.3s ease-in-out;
}
/* Show panel when opened */
.rpg-panel.rpg-mobile-open {
transform: translateY(0);
z-index: 999;
}
/* On mobile, panel is always at bottom */
.rpg-panel.rpg-position-right,
.rpg-panel.rpg-position-left,
.rpg-panel.rpg-position-top {
position: fixed;
top: auto;
bottom: 0;
left: 0;
right: 0;
width: 100%;
max-width: 100%;
height: 70vh;
max-height: 70vh;
border-radius: 20px 20px 0 0;
overflow-y: auto;
}
}
/* Extra small screens - more height */
@media (max-width: 480px) {
.rpg-panel.rpg-position-right,
.rpg-panel.rpg-position-left,
.rpg-panel.rpg-position-top {
height: 80vh;
max-height: 80vh;
}
.rpg-mobile-toggle {
bottom: 70px;
right: 15px;
width: 52px;
height: 52px;
font-size: 22px;
}
}
/* Touch-friendly improvements for mobile */
@media (max-width: 768px) {
/* Larger touch targets for buttons */
.rpg-classic-stat-btn {
min-width: 44px;
min-height: 44px;
font-size: 18px;
}
/* More padding for editable fields */
.rpg-editable {
padding: 8px;
min-height: 44px;
}
/* Larger close buttons */
.rpg-thought-close {
min-width: 44px;
min-height: 44px;
font-size: 24px;
}
}