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:
@@ -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.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user