Files
mc-webui/app/static/css/style.css
MarekWo 82c606569a fix: Replace sticky bar with proper FAB buttons
Previous sticky bar implementation took up vertical space in layout,
making viewport issues worse. Replaced with proper floating action
buttons that don't affect layout.

Changes:
- Remove sticky bar from index.html
- Add FAB container with fixed position (no layout impact)
- Two circular buttons: DM (green) and Contacts (blue)
- position: fixed, right: 16px, top: 80px
- z-index: 900 (lower than offcanvas menu 1045)
- Beautiful gradients and shadows
- Hover/active animations (scale transform)
- Mobile responsive (smaller on <768px)

Features:
- No vertical space taken (fixed position)
- Covered by offcanvas when menu opens (z-index hierarchy)
- Always visible in corner
- Uses navigateTo() for clean navigation

Test scenario:
1. Click FAB buttons (bypass offcanvas menu completely)
2. Navigate to DM / Contact Management
3. Return to main page
4. Check if status bar corruption still occurs

If FABs work: problem is in offcanvas cleanup
If FABs fail: problem is deeper in viewport/layout

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-01 19:17:28 +01:00

655 lines
13 KiB
CSS

/* mc-webui Custom Styles */
:root {
--msg-own-bg: #e7f1ff;
--msg-other-bg: #f8f9fa;
--msg-border: #dee2e6;
}
/* Page Layout */
html, body {
height: 100vh; /* Fallback for older browsers */
height: 100dvh; /* Dynamic viewport height (mobile-friendly) */
margin: 0;
overflow: hidden;
}
body {
display: flex;
flex-direction: column;
}
main {
flex: 1;
overflow: hidden;
display: flex;
flex-direction: column;
min-height: 0; /* Important for flex children */
}
/* Messages Container */
.messages-container {
background-color: #ffffff;
}
#messagesList {
display: flex;
flex-direction: column;
gap: 0.75rem;
}
/* Message Bubbles */
.message {
max-width: 70%;
padding: 0.75rem 1rem;
border-radius: 1rem;
border: 1px solid var(--msg-border);
word-wrap: break-word;
animation: fadeIn 0.3s ease-in;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
/* Own Messages (right-aligned) */
.message.own {
align-self: flex-end;
background-color: var(--msg-own-bg);
border-color: #b8daff;
}
/* Other Messages (left-aligned) */
.message.other {
align-self: flex-start;
background-color: var(--msg-other-bg);
}
/* Message Header */
.message-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 0.25rem;
font-size: 0.875rem;
}
.message-sender {
font-weight: 600;
color: #0d6efd;
}
.message.own .message-sender {
color: #084298;
}
.message-time {
font-size: 0.75rem;
color: #6c757d;
}
/* Message Content */
.message-content {
margin: 0;
white-space: pre-wrap;
line-height: 1.4;
}
/* Message Metadata */
.message-meta {
font-size: 0.7rem;
color: #adb5bd;
margin-top: 0.25rem;
}
/* Reply Button */
.btn-reply {
font-size: 0.7rem;
padding: 0.1rem 0.4rem;
margin-top: 0.25rem;
}
/* Send Form */
#messageInput,
#dmMessageInput {
resize: none;
border-radius: 0.5rem 0 0 0.5rem;
}
#sendBtn,
#dmSendBtn {
border-radius: 0 0.5rem 0.5rem 0;
}
/* Status Indicators */
.status-connected {
color: #198754 !important;
}
.status-disconnected {
color: #dc3545 !important;
}
.status-connecting {
color: #ffc107 !important;
}
/* Scrollbar Styling */
.messages-container::-webkit-scrollbar {
width: 8px;
}
.messages-container::-webkit-scrollbar-track {
background: #f1f1f1;
}
.messages-container::-webkit-scrollbar-thumb {
background: #888;
border-radius: 4px;
}
.messages-container::-webkit-scrollbar-thumb:hover {
background: #555;
}
/* Channel selector and date selector - larger font size */
#channelSelector,
#dateSelector {
font-size: 1rem;
}
/* Offcanvas menu styling */
.offcanvas {
width: 280px !important;
}
.offcanvas-body .list-group-item {
padding: 1rem 0.75rem;
border: none;
border-bottom: 1px solid #dee2e6;
font-size: 1rem;
}
.offcanvas-body .list-group-item:hover {
background-color: #f8f9fa;
}
.offcanvas-body .list-group-item i {
color: #0d6efd;
min-width: 1.5rem;
}
.offcanvas-body .list-group-item span {
font-weight: 500;
}
.offcanvas-body .list-group-item .form-select {
font-size: 1rem;
}
/* Responsive Design */
@media (max-width: 768px) {
.message,
.dm-message {
max-width: 85%;
}
.message-header {
font-size: 0.8rem;
}
#messageInput,
#dmMessageInput {
font-size: 0.9rem;
}
/* Reduce padding on mobile to save vertical space */
#sendMessageForm,
#dmSendForm {
padding: 0.5rem !important;
}
/* Make status bar more compact */
.row.border-top .p-2 {
padding: 0.3rem !important;
font-size: 0.7rem;
}
/* Navbar: Reduce gap between elements */
.navbar .d-flex {
gap: 0.25rem !important;
}
/* Navbar: Channel selector on mobile */
#channelSelector,
#dmConversationSelector {
min-width: 100px !important;
font-size: 0.9rem;
}
/* Navbar: Smaller buttons */
.navbar .btn-sm {
padding: 0.25rem 0.4rem;
font-size: 0.875rem;
}
/* Modal: Better mobile layout */
.modal-dialog {
margin: 0.5rem;
}
.modal-body {
padding: 0.75rem;
}
/* Modal: Smaller channel keys on mobile */
.list-group-item small {
font-size: 0.65rem;
word-break: break-all;
}
/* Modal: Compact channel list */
.modal .list-group-item {
padding: 0.5rem;
}
/* Modal: Stack buttons vertically on very small screens */
@media (max-width: 400px) {
.btn-group {
flex-direction: column;
}
.btn-group .btn {
border-radius: 0.375rem !important;
margin-bottom: 0.25rem;
}
}
}
/* Loading State */
.loading-spinner {
display: flex;
justify-content: center;
align-items: center;
height: 100%;
}
/* Empty State */
.empty-state {
text-align: center;
padding: 3rem 1rem;
color: #6c757d;
}
.empty-state i {
font-size: 3rem;
margin-bottom: 1rem;
opacity: 0.5;
}
/* Notification Bell Badge */
.notification-badge {
position: absolute;
top: -8px;
right: -8px;
background-color: #dc3545;
color: white;
border-radius: 10px;
padding: 2px 6px;
font-size: 0.65rem;
font-weight: bold;
line-height: 1;
min-width: 18px;
text-align: center;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
z-index: 10;
}
/* Bell Ring Animation */
@keyframes bell-ring {
0% { transform: rotate(0deg); }
10% { transform: rotate(14deg); }
20% { transform: rotate(-8deg); }
30% { transform: rotate(14deg); }
40% { transform: rotate(-4deg); }
50% { transform: rotate(10deg); }
60% { transform: rotate(0deg); }
100% { transform: rotate(0deg); }
}
.bell-ring {
animation: bell-ring 1s ease-in-out;
transform-origin: 50% 4px;
}
/* Notification Bell Container */
#notificationBell {
position: relative;
display: inline-flex;
align-items: center;
justify-content: center;
}
#notificationBell:hover .notification-badge {
transform: scale(1.1);
transition: transform 0.2s ease;
}
/* =============================================================================
Direct Messages (DM) Styles
============================================================================= */
/* DM Badge on notification bell (secondary badge, bottom-right, green) */
.notification-badge-dm {
position: absolute;
bottom: -6px;
right: -6px;
background-color: #198754;
color: white;
border-radius: 8px;
padding: 1px 4px;
font-size: 0.6rem;
font-weight: bold;
min-width: 14px;
text-align: center;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
z-index: 10;
}
/* DM Messages Container */
.dm-messages-container {
height: 50vh;
overflow-y: auto;
padding: 0.5rem;
display: flex;
flex-direction: column;
gap: 0.5rem;
background-color: #fafafa;
}
/* DM Messages List (flex container for message alignment) */
#dmMessagesList {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
@media (max-width: 576px) {
.dm-messages-container {
height: calc(100vh - 200px);
}
}
/* DM Message Bubbles */
.dm-message {
max-width: 70%;
padding: 0.75rem 1rem;
border-radius: 1rem;
word-wrap: break-word;
animation: fadeIn 0.3s ease-in;
}
.dm-message.own {
align-self: flex-end;
background-color: var(--msg-own-bg);
border: 1px solid #b8daff;
}
.dm-message.other {
align-self: flex-start;
background-color: var(--msg-other-bg);
border: 1px solid var(--msg-border);
}
/* DM Message Metadata */
.dm-meta {
font-size: 0.65rem;
color: #adb5bd;
margin-top: 0.25rem;
}
/* DM Status Indicators */
.dm-status {
font-size: 0.7rem;
margin-left: 0.25rem;
}
.dm-status.pending {
color: #ffc107;
}
.dm-status.delivered {
color: #198754;
}
.dm-status.timeout {
color: #dc3545;
}
/* DM Conversation List Item */
.dm-conversation-item {
padding: 0.75rem;
border-bottom: 1px solid #dee2e6;
cursor: pointer;
transition: background-color 0.15s ease;
}
.dm-conversation-item:hover {
background-color: #f8f9fa;
}
.dm-conversation-item.unread {
background-color: #e7f1ff;
}
.dm-conversation-item:last-child {
border-bottom: none;
}
/* DM Preview Text */
.dm-preview {
font-size: 0.85rem;
color: #6c757d;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 100%;
}
/* DM Button on channel messages - uses same class as Reply (.btn-reply) */
/* DM Empty State */
.dm-empty-state {
text-align: center;
padding: 2rem 1rem;
color: #6c757d;
}
.dm-empty-state i {
font-size: 2.5rem;
margin-bottom: 0.75rem;
opacity: 0.5;
}
/* DM Scrollbar */
.dm-messages-container::-webkit-scrollbar {
width: 6px;
}
.dm-messages-container::-webkit-scrollbar-track {
background: #f1f1f1;
}
.dm-messages-container::-webkit-scrollbar-thumb {
background: #ccc;
border-radius: 3px;
}
.dm-messages-container::-webkit-scrollbar-thumb:hover {
background: #aaa;
}
/* =============================================================================
Message Content Enhancements (Mentions, Links, Images)
============================================================================= */
/* Mention Badge (similar to Android Meshcore app) */
.mention-badge {
display: inline-block;
background-color: #0d6efd;
color: white;
padding: 0.15rem 0.5rem;
border-radius: 0.75rem;
font-size: 0.85em;
font-weight: 500;
margin: 0 0.1rem;
white-space: nowrap;
}
.message.own .mention-badge {
background-color: #084298;
}
/* Clickable Links in Messages */
.message-link {
color: #0d6efd;
text-decoration: underline;
word-break: break-all;
}
.message-link:hover {
color: #0a58ca;
text-decoration: underline;
}
.message.own .message-link {
color: #084298;
}
.message.own .message-link:hover {
color: #052c65;
}
/* Image Thumbnails in Messages */
.message-image-container {
margin-top: 0.5rem;
display: flex;
flex-direction: column;
gap: 0.25rem;
}
.message-image-thumbnail {
max-width: 300px;
max-height: 200px;
border-radius: 0.5rem;
cursor: pointer;
transition: transform 0.2s ease, box-shadow 0.2s ease;
border: 1px solid #dee2e6;
}
.message-image-thumbnail:hover {
transform: scale(1.02);
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
}
.message-image-url {
font-size: 0.75rem;
word-break: break-all;
}
/* Responsive image sizes on mobile */
@media (max-width: 576px) {
.message-image-thumbnail {
max-width: 200px;
max-height: 150px;
}
}
/* Image Preview Modal */
#imagePreviewModal .modal-content {
background-color: rgba(0, 0, 0, 0.95);
}
#imagePreviewModal .modal-body {
padding: 1rem;
}
#imagePreviewImg {
border-radius: 0.5rem;
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.3);
}
/* =============================================================================
TEST: Floating Action Buttons (FAB)
============================================================================= */
.fab-container {
position: fixed;
right: 16px;
top: 80px;
z-index: 900; /* Lower than offcanvas (1045) but higher than content */
display: flex;
flex-direction: column;
gap: 12px;
}
.fab {
width: 56px;
height: 56px;
border-radius: 50%;
border: none;
display: flex;
align-items: center;
justify-content: center;
font-size: 1.5rem;
cursor: pointer;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.fab:hover {
transform: scale(1.1);
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.4);
}
.fab:active {
transform: scale(0.95);
}
.fab-dm {
background: linear-gradient(135deg, #198754 0%, #157347 100%);
color: white;
}
.fab-contacts {
background: linear-gradient(135deg, #0d6efd 0%, #0a58ca 100%);
color: white;
}
/* Mobile optimization */
@media (max-width: 768px) {
.fab-container {
right: 12px;
top: 70px;
gap: 10px;
}
.fab {
width: 48px;
height: 48px;
font-size: 1.25rem;
}
}
/* =============================================================================
PWA Safe Area Handling
============================================================================= */
/* Ensure bottom UI is visible above system bars on mobile devices */
@supports (padding-bottom: env(safe-area-inset-bottom)) {
body {
padding-bottom: env(safe-area-inset-bottom);
}
}