From 49a325ebee495975b9a09bc4a90b293bdcbc4be8 Mon Sep 17 00:00:00 2001 From: Adam Lamers Date: Thu, 16 Apr 2026 22:04:14 -0400 Subject: [PATCH] responsive --- src/App.css | 1677 +---------------- src/auth/AuthGate.svelte | 135 ++ src/chat/ChatContainer.svelte | 437 +++-- src/chat/components/ChatInput.svelte | 28 +- src/chat/components/MemberList.svelte | 71 + src/chat/components/MessageItem.svelte | 53 +- src/chat/components/MessageList.svelte | 10 + src/chat/components/RichText.svelte | 70 +- src/chat/components/ServerList.svelte | 26 + .../channels/TextChannelGroup.svelte | 45 + .../channels/VoiceChannelGroup.svelte | 196 ++ 11 files changed, 1014 insertions(+), 1734 deletions(-) diff --git a/src/App.css b/src/App.css index 5294955..6ac0efb 100644 --- a/src/App.css +++ b/src/App.css @@ -13,7 +13,7 @@ } /* Premium Midnight Purple (Amethyst) */ -.theme-amethyst, :root { +.theme-amethyst { --background-primary: #1f1e22; --background-secondary: #19181c; --background-tertiary: #121114; @@ -108,7 +108,7 @@ } /* Generic Dark (Standard) */ -.theme-dark { +.theme-dark, :root { --background-primary: #2b2d31; --background-secondary: #232428; --background-tertiary: #1e1f22; @@ -145,7 +145,7 @@ --background-floating: #ffffff; } - +/* Reset & Foundation */ body { margin: 0; font-family: var(--font-primary); @@ -159,231 +159,18 @@ body { height: 100%; } -.chat-container { - display: flex; - height: 100vh; - width: 100vw; -} - -.left-sidebar-wrapper { - display: flex; - flex-direction: column; - width: calc(var(--server-sidebar-width) + var(--channel-sidebar-width)); - height: 100%; - flex-shrink: 0; - z-index: 100; - background-color: var(--background-secondary); -} - -.left-sidebar-top { - display: flex; - flex: 1; - min-height: 0; -} - -/* Server List */ -.server-list { - width: var(--server-sidebar-width); - background-color: var(--background-tertiary); - display: flex; - flex-direction: column; - align-items: center; - padding: 12px 0; - gap: 8px; - flex-shrink: 0; -} - -.server-icon { - width: 48px; - height: 48px; - background-color: var(--background-accent); - border-radius: 50%; - display: flex; - align-items: center; - justify-content: center; - cursor: pointer; - transition: - border-radius 0.2s, - background-color 0.2s; - font-weight: bold; - color: var(--text-normal); - position: relative; -} - -.server-icon:hover { - border-radius: 16px; - background-color: var(--brand); - color: white; -} - -.server-icon.active { - border-radius: 16px; - background-color: var(--brand); - color: white; -} - -.server-icon.active::before { - content: ""; - position: absolute; - left: -12px; +/* Shared UI Utility Classes */ +.status-dot { width: 8px; - height: 40px; - background-color: white; - border-radius: 0 4px 4px 0; -} - -/* Channel Sidebar */ -.sidebar-container { - display: flex; - flex-direction: column; - background-color: var(--background-secondary); - width: var(--channel-sidebar-width); - height: 100%; + height: 8px; + border-radius: 50%; flex-shrink: 0; - position: relative; - z-index: 100; } -.channel-sidebar { - flex: 1; - overflow-y: auto; - overflow-x: visible; - display: flex; - flex-direction: column; -} - -.server-header { - height: 48px; - padding: 0 16px; - display: flex; - align-items: center; - box-shadow: 0 1px 0 rgba(0, 0, 0, 0.2); - font-weight: bold; -} - -.server-header.clickable { - cursor: pointer; - transition: background-color 0.1s; -} - -.server-header.clickable:hover { - background-color: var(--background-modifier-hover); -} - -.server-dropdown { - background-color: var(--background-floating); - margin: 0 8px 8px 8px; - border-radius: 4px; - box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3); - overflow: hidden; - z-index: 100; -} - -.server-dropdown-item { - padding: 8px 12px; - font-size: 0.85rem; - cursor: pointer; - transition: background-color 0.1s; -} - -.server-dropdown-item:hover { - background-color: var(--brand); - color: white; -} - -.server-dropdown-item.danger:hover { - background-color: var(--status-danger); -} - -.server-dropdown-item.muted { - color: var(--text-muted); -} - -.server-dropdown-item.muted:hover { - color: white; -} - -.channel-section { - padding: 16px 8px; -} - -.section-header { - display: flex; - justify-content: space-between; - align-items: center; - padding: 0 8px; - font-size: 0.75rem; - font-weight: 700; - color: var(--text-muted); - margin-bottom: 4px; -} - -.add-btn { - background: none; - border: none; - color: var(--text-muted); - cursor: pointer; - font-size: 0.9rem; - line-height: 1; - padding: 0; - display: flex; - align-items: center; - justify-content: center; - opacity: 0; - transition: opacity 0.1s; -} - -.section-header:hover .add-btn { - opacity: 1; -} - -.add-btn:hover { - color: var(--interactive-hover); -} - -.channel-item { - padding: 6px 8px; - border-radius: 4px; - cursor: pointer; - display: flex; - align-items: center; - gap: 6px; - color: var(--interactive-normal); -} - -.channel-item:hover { - background-color: var(--background-accent); - color: var(--interactive-hover); -} - -.channel-item.active { - background-color: var(--background-modifier-selected); - color: white; -} - -.channel-item-hash { - font-size: 1em; - color: var(--text-muted); -} - -/* User Info Bar */ -.user-info-bar { - background-color: var(--background-tertiary); - padding: 0 8px; - display: flex; - align-items: center; - justify-content: space-between; - height: 52px; - flex-shrink: 0; - border-top: 1px solid rgba(255, 255, 255, 0.05); -} - -.user-info-main { - display: flex; - align-items: center; - gap: 8px; - min-width: 0; -} +.status-dot.green { background-color: var(--status-positive); } +.status-dot.yellow { background-color: var(--status-warning); } +.status-dot.red { background-color: var(--status-danger); } +.status-dot.grey { background-color: var(--text-muted); } .avatar { border-radius: 50%; @@ -397,169 +184,11 @@ body { color: white; } -.avatar.small { - width: 32px; - height: 32px; - font-size: 0.8rem; -} - -.avatar.tiny { - width: 24px; - height: 24px; - font-size: 0.65rem; -} - .avatar.talking { border: 2px solid var(--status-positive); box-shadow: 0 0 0 2px rgba(35, 165, 89, 0.15); } -/* Voice Member Item */ -.voice-member-list { - padding-left: 16px; - display: flex; - flex-direction: column; - gap: 2px; - margin-bottom: 8px; -} - -.voice-member-status-container { - margin-left: auto; - display: flex; - align-items: center; - height: 100%; - padding: 0 4px; - cursor: help; - gap: 6px; -} - -.voice-member-indicators { - display: flex; - align-items: center; - gap: 4px; -} - -.voice-indicator-icon { - font-size: 0.75rem; - color: var(--interactive-normal); - display: flex; - align-items: center; -} - -.deafen-indicator { - color: var(--interactive-normal) !important; -} - -.deafen-indicator-svg { - width: 1em; - height: 1em; - display: inline-block; - vertical-align: -0.125em; - color: var(--interactive-normal) !important; -} - -.icon-btn:hover .deafen-indicator, -.icon-btn:hover .deafen-indicator-svg { - color: var(--interactive-hover) !important; -} - -.voice-member-item { - display: flex; - align-items: center; - gap: 8px; - padding: 4px 8px; - margin: 0 4px; - border-radius: 4px; - cursor: pointer; - transition: background-color 0.1s; - position: relative; - height: 32px; -} - -.voice-member-item:hover { - background-color: var(--background-modifier-hover); -} - -.voice-member-name { - font-size: 0.9rem; - color: var(--text-muted); - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - font-weight: 500; - transition: color 0.1s; -} - -.voice-member-name.talking { - color: var(--header-primary); -} - -.watcher-eye { - color: var(--brand); - font-size: 0.75rem; - margin-left: 4px; - display: flex; - align-items: center; -} - -.avatar.talking { - border: 2px solid var(--status-positive); - box-shadow: 0 0 0 2px rgba(35, 165, 89, 0.15); -} - -.me-badge { - color: var(--text-muted); - font-size: 0.75rem; - margin-left: 4px; -} - -.member-item.offline { - opacity: 0.5; -} - -.member-name.talking { - color: var(--header-primary); -} - -.member-list-section-header { - padding: 16px 8px 8px 8px; - font-size: 0.75rem; - font-weight: 700; - color: var(--text-muted); - text-transform: uppercase; - letter-spacing: 0.02em; -} - -.member-list-section-header:first-child { - padding-top: 0; -} - -.user-details { - min-width: 0; -} - -.user-display-name { - font-size: 0.85rem; - font-weight: 600; - color: var(--header-primary); - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.user-status { - font-size: 0.7rem; - color: var(--text-muted); - display: flex; - align-items: center; - gap: 4px; -} - -.user-actions { - display: flex; - gap: 4px; -} - .icon-btn { background: none; border: none; @@ -571,6 +200,7 @@ body { align-items: center; justify-content: center; font-size: 1.1rem; + transition: all 0.2s; } .icon-btn:hover { @@ -578,972 +208,34 @@ body { color: var(--interactive-hover); } -.icon-btn.active { - color: var(--brand); -} +.icon-btn.active { color: var(--brand); } +.icon-btn.danger.active { color: var(--status-danger); } -.icon-btn.active:hover { - background-color: var(--background-modifier-selected); -} - -.icon-btn.danger.active { - color: var(--status-danger); -} - -/* Main Content Area */ -.main-content { - flex: 1; - display: flex; - flex-direction: column; - background-color: var(--background-primary); - min-width: 0; - position: relative; - z-index: 1; -} - -.notification-toggle { - padding: 4px; - margin-left: 4px; - color: var(--interactive-normal); - opacity: 0.6; - font-size: 0.9rem !important; -} - -.notification-toggle:hover { - opacity: 1; -} - -.notification-toggle.subscribed { - color: var(--status-positive); - opacity: 1; -} - -.chat-header { - height: 48px; - padding: 0 16px; - display: flex; - align-items: center; - gap: 8px; - box-shadow: 0 1px 0 rgba(0, 0, 0, 0.2); - font-weight: bold; - z-index: 10; -} - -.encryption-indicator { - display: flex; - align-items: center; - gap: 4px; - background-color: rgba(88, 101, 242, 0.1); - border: 1px solid rgba(88, 101, 242, 0.3); - color: var(--brand); - padding: 2px 6px; - border-radius: 4px; - font-size: 0.65rem; - font-weight: 700; - text-transform: uppercase; - margin-left: 4px; -} - -.message-list { - flex: 1; - overflow-y: auto; - display: flex; - flex-direction: column; - padding-top: 24px; -} - -.message-item { - padding: 8px 16px; - display: flex; - gap: 16px; - position: relative; -} - -.message-item.grouped { - padding-top: 4px; - padding-bottom: 4px; -} - -.message-item.grouped .message-header { - display: none; -} - -.message-avatar-placeholder { - width: 40px; - height: 20px; /* Match approximate line-height */ - flex-shrink: 0; - position: relative; - display: flex; - justify-content: center; -} - -.thread-message-item .message-avatar-placeholder { +.close-btn { width: 32px; -} - -.message-hover-timestamp { - position: absolute; - top: 0; - left: 0; - width: 100%; - text-align: center; - font-size: 0.65rem; - color: var(--text-muted); - opacity: 0; - pointer-events: none; - line-height: 1.4; - padding-top: 2px; -} - -.message-item.grouped:hover .message-hover-timestamp { - opacity: 1; -} - -.message-item:hover { - background-color: rgba(0, 0, 0, 0.05); -} - -.message-item.active { - background-color: var(--background-modifier-hover); -} - -.message-item.active::before { - content: ""; - position: absolute; - left: 0; - top: 0; - bottom: 0; - width: 2px; - background-color: var(--brand); -} - -.message-actions-toolbar { - position: absolute; - top: -16px; - right: 16px; - background-color: var(--background-primary); - border: 1px solid var(--background-accent); - border-radius: 4px; - display: flex; - box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); - z-index: 10; - opacity: 0; - pointer-events: none; - transition: opacity 0.1s; -} - -.message-item:hover .message-actions-toolbar { - opacity: 1; - pointer-events: auto; -} - -.message-actions-toolbar .toolbar-btn { - background: none; - border: none; - color: var(--interactive-normal); - cursor: pointer; - padding: 4px 8px; - display: flex; - align-items: center; - justify-content: center; - font-size: 1rem; - transition: - color 0.1s, - background-color 0.1s; -} - -.message-actions-toolbar .toolbar-btn:hover { - color: var(--interactive-hover); - background-color: var(--background-modifier-hover); -} - -.message-actions-toolbar .toolbar-btn:first-child { - border-radius: 4px 0 0 4px; -} - -.message-actions-toolbar .toolbar-btn:last-child { - border-radius: 0 4px 4px 0; -} - -.message-avatar { - width: 40px; - height: 40px; - font-size: 1rem; -} - -.message-content { - display: flex; - flex-direction: column; - min-width: 0; -} - -.message-header { - display: flex; - align-items: baseline; - gap: 8px; -} - -.user-name { - font-weight: 600; - color: var(--header-primary); -} - -.message-time { - font-size: 0.75rem; - color: var(--text-muted); -} - -.message-text { - line-height: 1.4; - word-wrap: break-word; -} - -.url-link { - color: #00a8fc; - text-decoration: none; -} - -.url-link:hover { - text-decoration: underline; -} - -.message-image-container { - margin-top: 8px; - max-width: 400px; - max-height: 300px; - border-radius: 8px; - overflow: hidden; - border: 1px solid var(--background-accent); - background-color: var(--background-tertiary); -} - -.message-image { - max-width: 100%; - max-height: 300px; - display: block; - object-fit: contain; - cursor: pointer; -} - -.thread-link { - font-size: 0.75rem; - color: var(--brand); - text-decoration: none; - cursor: pointer; -} - -.thread-link:hover { - text-decoration: underline; -} - -/* Embeds */ -.embeds-container { - display: flex; - flex-direction: column; - gap: 8px; - margin-top: 4px; -} - -.embed-wrapper.shadow-box { - border: 1px solid var(--background-modifier-accent); - border-radius: 8px; - background-color: var(--background-secondary); - box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); - overflow: hidden; - width: fit-content; - max-width: 100%; -} - -.embed-header { - display: flex; - justify-content: space-between; - align-items: center; - width: 100%; - padding: 8px 12px; - background-color: var(--background-tertiary); - border: none; - border-bottom: 1px solid var(--background-modifier-accent); - cursor: pointer; - font-family: inherit; - transition: background-color 0.2s; -} - -.embed-header:hover { - background-color: var(--background-modifier-hover); -} - -.embed-header.collapsed { - border-bottom: none; -} - -.embed-type-label { - display: flex; - align-items: center; - gap: 8px; - font-size: 0.85rem; - font-weight: bold; - color: var(--text-normal); -} - -.embed-content-body { - padding: 8px; - display: flex; - justify-content: center; - background-color: var(--background-secondary); -} - -.media-embed-container { - border-radius: 4px; - overflow: hidden; - width: fit-content; - max-width: 100%; -} - -.media-iframe { - display: block; - border: none; - max-width: 100%; -} - -/* Reactions */ -.reaction-badge { - background-color: var(--background-accent); - border: 1px solid transparent; - border-radius: 8px; - padding: 2px 6px; - display: flex; - align-items: center; - gap: 4px; - cursor: pointer; - transition: all 0.1s; - color: var(--text-normal); -} - -.reaction-badge:hover { - background-color: var(--background-modifier-hover); - border-color: var(--interactive-normal); -} - -.reaction-badge.active { - background-color: rgba(88, 101, 242, 0.15); - border-color: var(--brand); -} - -.reaction-badge.active .count { - color: var(--brand); -} - -.reaction-badge .emoji { - font-size: 1rem; -} - -.reaction-badge .count { - font-size: 0.8rem; - font-weight: 600; - color: var(--interactive-normal); -} - -.add-reaction-btn { - background: none; - border: none; - color: var(--interactive-normal); - cursor: pointer; - padding: 4px; - border-radius: 4px; - transition: opacity 0.2s; -} - -.add-reaction-btn:hover { - color: var(--interactive-hover); - background-color: var(--background-modifier-hover); -} - -/* Chat Input */ -.chat-input-container { - padding: 0 16px 12px 16px; - position: relative; - display: flex; - flex-direction: column; -} - -.typing-indicator { - height: 20px; - margin-left: 16px; - margin-bottom: 2px; - font-size: 0.75rem; - color: var(--text-normal); - display: flex; - align-items: center; - gap: 8px; - pointer-events: none; - z-index: 20; -} - -.typing-indicator .dots { - display: flex; - gap: 2px; -} - -.typing-indicator .dot { - width: 4px; - height: 4px; - background-color: var(--text-muted); + height: 32px; border-radius: 50%; - animation: typing-dot 1.4s infinite ease-in-out; -} - -.typing-indicator .dot:nth-child(2) { - animation-delay: 0.2s; -} - -.typing-indicator .dot:nth-child(3) { - animation-delay: 0.4s; -} - -@keyframes typing-dot { - 0%, - 80%, - 100% { - transform: translateY(0); - } - 40% { - transform: translateY(-4px); - } -} - -.chat-input { - background-color: var(--background-tertiary); - border-radius: 8px; - padding: 0 16px; - display: flex; - align-items: center; -} - -.chat-input-wrapper { - background-color: var(--background-secondary); - border-radius: 8px; - padding: 0 12px; - display: flex; - align-items: center; -} - -/* Video Chat Layout */ -.video-grid { - flex: 1; - display: flex; - flex-direction: column; - padding: 16px; - background-color: var(--background-primary); - overflow: hidden; -} - -.video-grid-content { - display: grid; - gap: 16px; - width: 100%; - height: 100%; - grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); - align-content: start; -} - -/* Layout when someone is sharing/focused */ -.video-grid.has-sharer .video-grid-content { - display: flex; - flex-direction: column; - gap: 16px; - height: 100%; - overflow: hidden; -} - -.video-tile-container.is-hero { - flex: 1; - min-height: 0; - width: 100%; -} - -/* We'll add a row-container to wrap only the row items in VideoGrid.svelte */ -.video-participants-row { - display: flex; - gap: 12px; - height: 160px; - overflow-x: auto; - overflow-y: hidden; - padding-bottom: 4px; /* Space for scrollbar */ - flex-shrink: 0; -} - -.video-tile-container.is-grid { - width: 100%; - aspect-ratio: 16 / 9; -} - -.video-tile-container.is-row { - width: 284px; /* 16:9 aspect for 160px height is 284px */ - flex-shrink: 0; - height: 100%; -} - -.video-tile { - position: relative; - background-color: var(--background-tertiary); - border-radius: 8px; - display: flex; - align-items: center; - justify-content: center; - overflow: hidden; - border: 2px solid transparent; - width: 100%; - height: 100%; -} - -.video-tile:not(.hero) { - aspect-ratio: 16 / 9; -} - -.video-tile.hero { - flex: 1; -} - -.video-tile.talking { - border-color: var(--status-positive); -} - -.video-tile video { - width: 100%; - height: 100%; - object-fit: contain; - background-color: black; -} - -.video-controls, -.tile-actions-right { - position: absolute; - display: flex; - gap: 8px; - opacity: 0; - transition: opacity 0.2s; - z-index: 10; -} - -.video-controls { - top: 8px; - right: 8px; -} - -.tile-actions-right { - bottom: 8px; - right: 8px; - display: flex; - align-items: center; - gap: 8px; -} - -.volume-control-container { - display: flex; - align-items: center; - gap: 8px; - background-color: rgba(30, 31, 34, 0.85); - padding: 4px 8px; - border-radius: 4px; - transition: background-color 0.2s; -} - -.volume-control-container:hover { - background-color: rgba(43, 45, 49, 0.95); -} - -.volume-slider { - cursor: pointer; - height: 4px; - -webkit-appearance: none; - background: rgba(255, 255, 255, 0.2); - border-radius: 2px; - outline: none; - margin: 0; - padding: 0; - accent-color: white; - transition: - width 0.2s, - opacity 0.2s; -} - -/* Default for VideoTile is hidden until hover */ -.volume-control-container .volume-slider { - width: 0; - opacity: 0; -} - -.volume-control-container:hover .volume-slider { - width: 80px; - opacity: 1; -} - -/* Context menu slider is always visible and full width */ -.context-menu-section .volume-slider { - width: 100%; - opacity: 1; - display: block; - margin: 4px 0; -} - -.volume-slider::-webkit-slider-runnable-track { - width: 100%; - height: 4px; - cursor: pointer; - background: rgba(255, 255, 255, 0.2); - border-radius: 2px; -} - -.volume-slider::-webkit-slider-thumb { - -webkit-appearance: none; - width: 14px; - height: 14px; - background: white; - border-radius: 50%; - cursor: pointer; - margin-top: -5px; /* Centers thumb on 4px track */ border: none; - box-shadow: 0 1px 4px rgba(0, 0, 0, 0.5); -} - -.volume-slider::-moz-range-track { - width: 100%; - height: 4px; - cursor: pointer; - background: rgba(255, 255, 255, 0.2); - border-radius: 2px; -} - -.volume-slider::-moz-range-thumb { - width: 14px; - height: 14px; - background: white; - border-radius: 50%; - cursor: pointer; - border: none; - box-shadow: 0 1px 4px rgba(0, 0, 0, 0.5); -} - -.volume-control-container .mute-tile-btn { background-color: transparent; - padding: 4px; - min-width: 24px; -} - -.volume-control-container .mute-tile-btn:hover { - background-color: rgba(255, 255, 255, 0.1); -} - -.video-tile:hover .video-controls, -.video-tile:hover .tile-actions-right { - opacity: 1; -} - -.watch-btn, -.mute-tile-btn { - background-color: var(--brand); - color: white; - border: none; - padding: 4px 12px; - border-radius: 4px; - cursor: pointer; - font-weight: 500; - display: flex; - align-items: center; - justify-content: center; -} - -.watch-btn.active, -.mute-tile-btn { - background-color: rgba(30, 31, 34, 0.7); -} - -.watch-btn.active:hover, -.mute-tile-btn:hover { - background-color: rgba(43, 45, 49, 0.9); -} - -.fullscreen-btn { - background-color: rgba(0, 0, 0, 0.5); - color: white; - border: none; - padding: 4px 8px; - border-radius: 4px; - cursor: pointer; -} - -.avatar-placeholder-container { - display: flex; - flex-direction: column; - align-items: center; - gap: 12px; -} - -.avatar-placeholder { - width: 60px; - height: 60px; - border-radius: 50%; - background-color: var(--brand); - display: flex; - align-items: center; - justify-content: center; - font-size: 1.5rem; - font-weight: bold; -} - -.tile-info { - position: absolute; - bottom: 8px; - left: 8px; - background-color: rgba(0, 0, 0, 0.5); - padding: 2px 8px; - border-radius: 4px; - display: flex; - align-items: center; - gap: 6px; -} - -.tile-info .user-name { - font-size: 0.85rem; - color: white; -} - -.sharing-badge { - background-color: var(--status-danger); - color: white; - font-size: 0.6rem; - padding: 1px 4px; - border-radius: 2px; - font-weight: bold; -} - -/* Member List */ -.member-list { - padding: 16px 8px; - display: flex; - flex-direction: column; - gap: 2px; - overflow-y: auto; - height: 100%; -} - -.member-item { - display: flex; - align-items: center; - gap: 12px; - padding: 6px 8px; - border-radius: 4px; - cursor: pointer; color: var(--interactive-normal); -} - -.member-item:hover { - background-color: var(--background-modifier-hover); - color: var(--interactive-hover); -} - -.member-avatar { - border-radius: 50%; - flex-shrink: 0; -} - -.status-dot { - width: 8px; - height: 8px; - border-radius: 50%; - flex-shrink: 0; - cursor: help; -} - -.status-dot.green { - background-color: var(--status-positive); -} - -.status-dot.yellow { - background-color: var(--status-warning); -} - -.status-dot.red { - background-color: var(--status-danger); -} -.status-dot.grey { - background-color: var(--text-muted); -} - -/* Connection Popover */ -.connection-popover { - position: fixed; - width: 216px; - background-color: var(--background-floating, #1e1f22); - border-radius: 8px; - padding: 12px; - box-shadow: 0 8px 16px rgba(0, 0, 0, 0.24); - z-index: 3000; - color: var(--text-normal, #dbdee1); - font-family: var(--font-primary); - pointer-events: none; -} - -.connection-popover::before { - content: ""; - position: absolute; - top: 20px; - left: -6px; - width: 12px; - height: 12px; - background-color: var(--background-floating); - transform: rotate(45deg); -} - -.popover-header { - display: flex; - justify-content: space-between; - align-items: center; - margin-bottom: 12px; - padding-bottom: 8px; - border-bottom: 1px solid rgba(255, 255, 255, 0.1); -} - -.popover-name { - font-weight: bold; - font-size: 0.9rem; -} - -.popover-status { - font-size: 0.7rem; - text-transform: uppercase; - font-weight: 800; -} - -.popover-status.green { - color: var(--status-positive); -} -.popover-status.yellow { - color: var(--status-warning); -} -.popover-status.red { - color: var(--status-danger); -} - -.popover-info { - font-size: 0.8rem; - color: var(--text-muted); - font-style: italic; -} - -.stats-section { - margin-bottom: 12px; -} - -.stats-section:last-child { - margin-bottom: 0; -} - -.section-title { - font-size: 0.65rem; - font-weight: 800; - color: var(--text-muted); - margin-bottom: 4px; -} - -.stat-row { - display: flex; - justify-content: space-between; - font-size: 0.75rem; - line-height: 1.4; -} - -.stat-row span:last-child { - color: var(--header-primary); - font-family: var(--font-code); -} - -.member-name { - font-size: 0.9rem; - font-weight: 500; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -/* Right Sidebar (Users/Thread) */ -.right-sidebar { - width: 240px; - background-color: var(--background-secondary); - display: flex; - flex-direction: column; - flex-shrink: 0; - border-left: 1px solid rgba(0, 0, 0, 0.2); - position: relative; - z-index: 100; -} - -.thread-view { - flex: 1; - display: flex; - flex-direction: column; -} - -.thread-header { - height: 48px; - padding: 0 16px; - display: flex; - align-items: center; - box-shadow: 0 1px 0 rgba(0, 0, 0, 0.2); - font-weight: bold; -} - -.thread-messages-list { - padding: 8px 0; -} - -.thread-message-item { - padding: 4px 16px; - gap: 12px; -} - -/* Modals */ -.modal-overlay { - position: fixed; - top: 0; - left: 0; - right: 0; - bottom: 0; - background-color: rgba(0, 0, 0, 0.8); display: flex; align-items: center; justify-content: center; - z-index: 2000; + cursor: pointer; + transition: all 0.2s; } -.modal-content { - background-color: var(--background-primary); - padding: 24px; - border-radius: 8px; - width: 400px; - display: flex; - flex-direction: column; - gap: 16px; +.close-btn:hover { + color: var(--interactive-hover); + background-color: var(--background-modifier-hover); + transform: rotate(90deg); } -.modal-content h2 { - margin: 0; -} - -.modal-content input { - background-color: var(--background-tertiary); - border: none; - padding: 10px; - border-radius: 4px; - color: white; -} - -.modal-actions { - display: flex; - justify-content: flex-end; - gap: 12px; +.shadow-box { + box-shadow: 0 8px 16px rgba(0, 0, 0, 0.24); } +/* Button Utilities */ .btn-primary { background-color: var(--brand); color: white; @@ -1570,24 +262,21 @@ body { } .btn-secondary { - background-color: transparent; - border: 1px solid var(--brand); - color: var(--brand); + background-color: var(--background-accent); + border: 1px solid var(--background-modifier-accent); + color: var(--text-normal); padding: 10px 20px; border-radius: 4px; cursor: pointer; font-weight: 600; - transition: - background-color 0.2s, - color 0.2s; + transition: background-color 0.2s; display: flex; align-items: center; justify-content: center; } .btn-secondary:hover { - background-color: var(--brand); - color: white; + background-color: var(--background-modifier-hover); } .btn-danger { @@ -1598,269 +287,79 @@ body { border-radius: 4px; cursor: pointer; font-weight: 600; - transition: background-color 0.2s; - display: flex; - align-items: center; - justify-content: center; + transition: opacity 0.2s; } .btn-danger:hover { - background-color: var(--status-danger); -} - -.btn-danger.small { - padding: 4px 12px; - font-size: 0.8rem; -} - -.btn-ghost { - background-color: transparent; - color: var(--text-muted); - border: none; - padding: 8px 16px; - border-radius: 4px; - cursor: pointer; - font-weight: 600; - transition: - background-color 0.2s, - color 0.2s; - display: flex; - align-items: center; - justify-content: center; -} - -.btn-ghost:hover { - background-color: var(--background-modifier-hover); - color: var(--text-normal); -} - -/* Login Screen */ -.login-screen { - display: flex; - align-items: center; - justify-content: center; - height: 100vh; - width: 100vw; - background: radial-gradient( - circle at center, - var(--background-secondary) 0%, - var(--background-tertiary) 100% - ); - background-color: var(--background-tertiary); -} - -.login-card { - background-color: var(--background-primary); - padding: 32px; - border-radius: 8px; - width: 480px; - box-shadow: 0 2px 10px 0 rgba(0, 0, 0, 0.2); - display: flex; - flex-direction: column; - align-items: center; - text-align: center; -} - -.login-card h1 { - color: var(--header-primary); - margin-bottom: 8px; - font-size: 24px; - font-weight: 600; -} - -.login-card p { - color: var(--text-normal); - margin-bottom: 24px; - font-size: 16px; -} - -.login-error { - color: var(--status-danger); - background-color: rgba(250, 119, 122, 0.1); - border: 1px solid rgba(250, 119, 122, 0.2); - padding: 8px; - border-radius: 4px; - margin-bottom: 16px; - width: 100%; - font-size: 0.9rem; -} - -/* Voice Connected Bar */ -.voice-status-bar { - background-color: var(--background-tertiary); - padding: 8px; - display: flex; - justify-content: space-between; - align-items: center; - border-top: 1px solid rgba(255, 255, 255, 0.05); -} - -.voice-info { - display: flex; - flex-direction: column; -} - -.voice-connected-text { - color: var(--status-positive); - font-size: 0.8rem; - font-weight: bold; -} - -.voice-channel-name { - color: var(--text-muted); - font-size: 0.75rem; -} - -.screen-share-btn { - background-color: var(--background-accent); - color: white; - border: none; - padding: 4px 12px; - border-radius: 4px; - cursor: pointer; - font-size: 0.8rem; - font-weight: 600; - transition: background-color 0.2s; -} - -.screen-share-btn:hover { - background-color: var(--background-modifier-hover); -} - -.screen-share-btn.active { - background-color: var(--status-danger); -} - -.screen-share-btn.active:hover { opacity: 0.9; } -.screen-share-controls { - display: flex; - align-items: center; - gap: 8px; +/* Embeds & Media */ +.embed-wrapper { + border-left: 4px solid var(--brand); background-color: var(--background-secondary); - padding: 2px 4px 2px 8px; - border-radius: 6px; - border: 1px solid var(--background-modifier-accent); -} - -.stream-settings-header { - display: flex; - gap: 4px; -} - -.setting-group-header select { - background: none; - border: none; - color: var(--text-muted); - font-size: 0.75rem; - font-weight: 600; - cursor: pointer; - padding: 2px 4px; - outline: none; border-radius: 4px; + margin-top: 8px; + max-width: 520px; + overflow: hidden; } -.setting-group-header select:hover { - color: var(--text-normal); - background-color: var(--background-modifier-hover); -} - -.setting-group-header select option { - background-color: var(--background-floating); - color: var(--text-normal); -} - -/* Context Menu */ -.context-menu { - position: fixed; - z-index: 3000; - background: var(--background-floating); - border-radius: 4px; - padding: 8px; - min-width: 180px; - box-shadow: 0 8px 16px rgba(0, 0, 0, 0.24); - border: 1px solid rgba(255, 255, 255, 0.05); -} - -.context-menu-header { - padding: 8px; - font-size: 0.75rem; - font-weight: bold; - color: var(--text-muted); - text-transform: uppercase; - border-bottom: 1px solid rgba(255, 255, 255, 0.06); - margin-bottom: 4px; -} - -.context-menu-separator { - height: 1px; - background-color: rgba(255, 255, 255, 0.06); - margin: 4px 0; -} - -.context-menu-item { - padding: 8px; +.embed-header { + padding: 8px 12px; display: flex; justify-content: space-between; align-items: center; cursor: pointer; - border-radius: 2px; - font-size: 0.9rem; - color: white; } -.context-menu-item:hover { - background: var(--brand); - color: white; -} - -.context-menu-section { - padding: 8px; - border-top: 1px solid rgba(255, 255, 255, 0.06); - margin-top: 4px; -} - -.context-menu-section label { - display: block; - font-size: 0.75rem; - font-weight: bold; - color: var(--text-muted); - text-transform: uppercase; - margin-bottom: 8px; -} - -.context-menu-section .volume-slider { - width: 100%; - opacity: 1; - display: block; - margin: 4px 0; -} - -.context-menu-section div:last-child { - font-size: 0.7rem; - text-align: right; - margin-top: 4px; -} - -/* Global Close Button */ -.close-btn { - width: 32px; - height: 32px; - border-radius: 50%; - border: none; - background-color: transparent; - color: var(--interactive-normal); - display: flex; - align-items: center; - justify-content: center; - cursor: pointer; - transition: all 0.2s; -} - -.close-btn:hover { - color: var(--interactive-hover); +.embed-header:hover { background-color: var(--background-modifier-hover); - transform: rotate(90deg); +} + +.embed-content { + padding: 0 12px 12px 12px; +} + +.embed-title { + font-weight: 600; + color: var(--header-primary); + margin-bottom: 4px; + display: block; + text-decoration: none; +} + +.embed-title:hover { + text-decoration: underline; +} + +.embed-description { + font-size: 0.9rem; + color: var(--text-normal); + line-height: 1.3; +} + +.media-embed-container { + margin-top: 8px; + border-radius: 4px; + overflow: hidden; + background-color: #000; + line-height: 0; +} + +/* Scrollbar Styling */ +::-webkit-scrollbar { + width: 8px; +} + +::-webkit-scrollbar-track { + background: transparent; +} + +::-webkit-scrollbar-thumb { + background: rgba(0, 0, 0, 0.2); + border-radius: 4px; +} + +::-webkit-scrollbar-thumb:hover { + background: rgba(0, 0, 0, 0.3); } diff --git a/src/auth/AuthGate.svelte b/src/auth/AuthGate.svelte index d4e0b59..4dd11e2 100644 --- a/src/auth/AuthGate.svelte +++ b/src/auth/AuthGate.svelte @@ -181,11 +181,146 @@ + +
+

Technical Specifications

+
+
+ + Svelte 5 +
+
+ + SpacetimeDB +
+
+ + Rust / WASM +
+
+ + WebRTC Mesh +
+
+ + GPG E2EE +
+
+ + Tauri 2.0 +
+
+
{/if} diff --git a/src/chat/components/ChatInput.svelte b/src/chat/components/ChatInput.svelte index 3351742..dd81ed1 100644 --- a/src/chat/components/ChatInput.svelte +++ b/src/chat/components/ChatInput.svelte @@ -724,6 +724,16 @@ .chat-input, .chat-input-wrapper { transition: border-radius 0.2s; + display: flex; + align-items: flex-end; + padding: 0 12px; + background-color: var(--background-tertiary); + border-radius: 8px; + gap: 4px; + } + + .chat-input-wrapper { + background-color: var(--background-secondary); } .has-staged { @@ -731,21 +741,7 @@ border-top-right-radius: 0 !important; } - .thread-input-inner .chat-input-wrapper textarea { - font-size: 1rem; - background: none; - border: none; - outline: none; - color: var(--text-normal); - width: 100%; - resize: none; - padding: 11px 0; - font-family: inherit; - line-height: 1.375rem; - box-sizing: border-box; - } - - .chat-input textarea { + .chat-input textarea, .chat-input-wrapper textarea { background: none; border: none; outline: none; @@ -761,7 +757,7 @@ width: 100%; } - .chat-input { + .chat-input, .chat-input-wrapper { height: auto !important; min-height: 44px; } diff --git a/src/chat/components/MemberList.svelte b/src/chat/components/MemberList.svelte index 9b78ea5..2a42556 100644 --- a/src/chat/components/MemberList.svelte +++ b/src/chat/components/MemberList.svelte @@ -131,4 +131,75 @@ text-overflow: ellipsis; line-height: 1; } + + .right-sidebar { + width: 240px; + background-color: var(--background-secondary); + display: flex; + flex-direction: column; + flex-shrink: 0; + border-left: 1px solid rgba(0, 0, 0, 0.2); + position: relative; + z-index: 100; + } + + .member-list { + padding: 16px 8px; + display: flex; + flex-direction: column; + gap: 2px; + overflow-y: auto; + height: 100%; + } + + .member-item { + display: flex; + align-items: center; + gap: 12px; + padding: 6px 8px; + border-radius: 4px; + cursor: pointer; + color: var(--interactive-normal); + transition: all 0.1s; + } + + .member-item:hover { + background-color: var(--background-modifier-hover); + color: var(--interactive-hover); + } + + .member-item.offline { + opacity: 0.45; + } + + .member-name { + font-size: 0.9rem; + font-weight: 500; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + + .member-name.talking { + color: var(--status-positive); + } + + .member-list-section-header { + padding: 16px 8px 8px 8px; + font-size: 0.75rem; + font-weight: 700; + color: var(--text-muted); + text-transform: uppercase; + letter-spacing: 0.02em; + } + + .sharing-badge { + background-color: var(--status-danger); + color: white; + font-size: 0.6rem; + padding: 1px 4px; + border-radius: 2px; + font-weight: bold; + margin-right: 4px; + } diff --git a/src/chat/components/MessageItem.svelte b/src/chat/components/MessageItem.svelte index 967d9ac..2e52e51 100644 --- a/src/chat/components/MessageItem.svelte +++ b/src/chat/components/MessageItem.svelte @@ -454,7 +454,7 @@ aria-expanded={!collapsedImages} >
- + {msg.imageIds.length} Image{msg.imageIds.length > 1 ? 's' : ''}
@@ -764,6 +764,57 @@ border-top-color: var(--background-floating); } + .message-image { + cursor: pointer; + display: block; + max-width: 100%; + border-radius: 4px; + object-fit: contain; + } + + .message-image-container { + max-width: 100%; + overflow: hidden; + cursor: pointer; + } + + .embed-wrapper { + border-left: 4px solid var(--brand); + background-color: var(--background-secondary); + border-radius: 4px; + max-width: 520px; + overflow: hidden; + } + + .embed-header { + width: 100%; + padding: 8px 12px; + display: flex; + justify-content: space-between; + align-items: center; + cursor: pointer; + background: none; + border: none; + font-family: inherit; + color: var(--text-normal); + } + + .embed-header:hover { + background-color: var(--background-modifier-hover); + } + + .embed-type-label { + display: flex; + align-items: center; + gap: 8px; + font-size: 0.85rem; + font-weight: bold; + } + + .embed-content-body { + padding: 8px 12px 12px 12px; + } + .reaction-badge { background-color: var(--background-accent); border: 1px solid transparent; diff --git a/src/chat/components/MessageList.svelte b/src/chat/components/MessageList.svelte index 70b7ec3..18dddda 100644 --- a/src/chat/components/MessageList.svelte +++ b/src/chat/components/MessageList.svelte @@ -414,4 +414,14 @@ max-width: 400px; line-height: 1.4; } + + .message-list { + flex: 1; + overflow-y: auto; + overflow-x: hidden; + display: flex; + flex-direction: column; + padding-top: 24px; + min-height: 0; + } diff --git a/src/chat/components/RichText.svelte b/src/chat/components/RichText.svelte index 0bdc122..ec09696 100644 --- a/src/chat/components/RichText.svelte +++ b/src/chat/components/RichText.svelte @@ -191,9 +191,9 @@ {:else if embed.type === 'facebook'} Facebook {:else if embed.type === 'image'} - Image + Image {:else} - Link + Link {/if} @@ -322,5 +322,71 @@ .message-image { cursor: pointer; + max-width: 100%; + max-height: 400px; + display: block; + border-radius: 4px; + object-fit: contain; + } + + .embeds-container { + display: flex; + flex-direction: column; + gap: 8px; + margin-top: 4px; + } + + .embed-wrapper { + border-left: 4px solid var(--brand); + background-color: var(--background-secondary); + border-radius: 4px; + max-width: 520px; + overflow: hidden; + } + + .embed-header { + width: 100%; + padding: 8px 12px; + display: flex; + justify-content: space-between; + align-items: center; + cursor: pointer; + background: none; + border: none; + font-family: inherit; + color: var(--text-normal); + } + + .embed-header:hover { + background-color: var(--background-modifier-hover); + } + + .embed-type-label { + display: flex; + align-items: center; + gap: 8px; + font-size: 0.85rem; + font-weight: bold; + } + + .embed-content-body { + padding: 8px 12px 12px 12px; + } + + .media-embed-container { + border-radius: 4px; + overflow: hidden; + background-color: #000; + line-height: 0; + } + + .media-iframe { + max-width: 100%; + border: none; + } + + .message-image-container { + max-width: 100%; + overflow: hidden; } diff --git a/src/chat/components/ServerList.svelte b/src/chat/components/ServerList.svelte index 66ad0a3..d2aea2d 100644 --- a/src/chat/components/ServerList.svelte +++ b/src/chat/components/ServerList.svelte @@ -261,4 +261,30 @@ background-color: var(--brand); color: white; } + + .server-list { + width: var(--server-sidebar-width); + background-color: var(--background-tertiary); + display: flex; + flex-direction: column; + align-items: center; + padding: 12px 0; + gap: 8px; + flex-shrink: 0; + height: 100%; + overflow-y: auto; + overflow-x: hidden; + } + + .server-icon.active::before { + content: ""; + position: absolute; + left: -4px; + top: 50%; + transform: translateY(-50%); + width: 8px; + height: 40px; + background-color: white; + border-radius: 0 4px 4px 0; + } diff --git a/src/chat/components/channels/TextChannelGroup.svelte b/src/chat/components/channels/TextChannelGroup.svelte index 16e8674..b39d2e7 100644 --- a/src/chat/components/channels/TextChannelGroup.svelte +++ b/src/chat/components/channels/TextChannelGroup.svelte @@ -76,4 +76,49 @@ background-color: rgba(255, 255, 255, 0.1); color: white; } + + .channel-section { + padding: 16px 0 8px 0; + } + + .section-header { + display: flex; + justify-content: space-between; + align-items: center; + padding: 0 16px; + font-size: 0.75rem; + font-weight: 700; + color: var(--text-muted); + margin-bottom: 4px; + } + + .add-btn { + background: none; + border: none; + color: var(--text-muted); + cursor: pointer; + font-size: 0.9rem; + padding: 4px; + display: flex; + align-items: center; + justify-content: center; + opacity: 0; + transition: opacity 0.1s, color 0.1s; + } + + .section-header:hover .add-btn { + opacity: 1; + } + + .add-btn:hover { + color: var(--interactive-hover); + } + + .channel-item-hash { + font-size: 1.2rem; + color: var(--text-muted); + margin-right: 4px; + width: 20px; + text-align: center; + } diff --git a/src/chat/components/channels/VoiceChannelGroup.svelte b/src/chat/components/channels/VoiceChannelGroup.svelte index ec7710d..bce898d 100644 --- a/src/chat/components/channels/VoiceChannelGroup.svelte +++ b/src/chat/components/channels/VoiceChannelGroup.svelte @@ -257,4 +257,200 @@ background-color: rgba(255, 255, 255, 0.1); color: white; } + + .channel-section { + padding: 16px 0 8px 0; + } + + .section-header { + display: flex; + justify-content: space-between; + align-items: center; + padding: 0 16px; + font-size: 0.75rem; + font-weight: 700; + color: var(--text-muted); + margin-bottom: 4px; + } + + .add-btn { + background: none; + border: none; + color: var(--text-muted); + cursor: pointer; + font-size: 0.9rem; + padding: 4px; + display: flex; + align-items: center; + justify-content: center; + opacity: 0; + transition: opacity 0.1s, color 0.1s; + } + + .section-header:hover .add-btn { + opacity: 1; + } + + .add-btn:hover { + color: var(--interactive-hover); + } + + .channel-item-hash { + font-size: 1.2rem; + color: var(--text-muted); + margin-right: 4px; + width: 20px; + text-align: center; + } + + /* Voice Member List Styles */ + .voice-member-list { + padding-left: 36px; + padding-right: 8px; + display: flex; + flex-direction: column; + gap: 1px; + margin-bottom: 8px; + } + + .voice-member-item { + display: flex; + align-items: center; + gap: 8px; + padding: 4px 6px; + border-radius: 4px; + cursor: pointer; + transition: background-color 0.1s; + height: 32px; + } + + .voice-member-item:hover { + background-color: var(--background-modifier-hover); + } + + .voice-member-name { + font-size: 0.85rem; + color: var(--text-muted); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + font-weight: 500; + } + + .voice-member-name.talking { + color: var(--header-primary); + } + + .voice-member-status-container { + margin-left: auto; + display: flex; + align-items: center; + gap: 4px; + } + + .voice-member-indicators { + display: flex; + align-items: center; + gap: 4px; + } + + .voice-indicator-icon { + font-size: 0.75rem; + color: var(--interactive-normal); + display: flex; + align-items: center; + } + + .deafen-indicator-svg { + width: 0.9rem; + height: 0.9rem; + } + + .watcher-eye { + color: var(--brand); + font-size: 0.75rem; + margin-left: 4px; + } + + .sharing-badge { + background-color: var(--status-danger); + color: white; + font-size: 0.6rem; + padding: 1px 4px; + border-radius: 2px; + font-weight: bold; + } + + /* Connection Popover */ + .connection-popover { + position: fixed; + width: 216px; + background-color: var(--background-floating); + border-radius: 8px; + padding: 12px; + box-shadow: 0 8px 16px rgba(0, 0, 0, 0.4); + z-index: 3000; + color: var(--text-normal); + pointer-events: none; + border: 1px solid var(--background-modifier-accent); + } + + .popover-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 12px; + padding-bottom: 8px; + border-bottom: 1px solid rgba(255, 255, 255, 0.1); + } + + .popover-name { + font-weight: bold; + font-size: 0.9rem; + } + + .popover-status { + font-size: 0.7rem; + text-transform: uppercase; + font-weight: 800; + } + + .popover-status.green { color: var(--status-positive); } + .popover-status.yellow { color: var(--status-warning); } + .popover-status.red { color: var(--status-danger); } + + .popover-info { + font-size: 0.8rem; + color: var(--text-muted); + font-style: italic; + } + + .stats-section { + margin-bottom: 12px; + } + + .section-title { + font-size: 0.65rem; + font-weight: 800; + color: var(--text-muted); + margin-bottom: 4px; + } + + .stat-row { + display: flex; + justify-content: space-between; + font-size: 0.75rem; + line-height: 1.4; + } + + .stat-row span:last-child { + color: var(--header-primary); + font-family: var(--font-code); + } + + .volume-slider { + width: 60px; + height: 4px; + accent-color: var(--brand); + }