Frontend color overhaul

This commit is contained in:
Jack Kingsman
2026-02-16 16:45:05 -08:00
parent 24685038f8
commit 877649ddc7
10 changed files with 141 additions and 88 deletions

View File

@@ -6,7 +6,7 @@
<meta name="mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
<meta name="apple-mobile-web-app-title" content="MCTerm" />
<meta name="theme-color" content="#0a0a0a" />
<meta name="theme-color" content="#111419" />
<meta name="description" content="Web interface for MeshCore mesh radio networks. Send and receive messages, manage contacts and channels, and configure your radio." />
<title>RemoteTerm for MeshCore</title>
<link rel="icon" type="image/png" href="/favicon-96x96.png" sizes="96x96" />

View File

@@ -925,12 +925,14 @@ export function App() {
const settingsSidebarContent = (
<div className="sidebar w-60 h-full min-h-0 bg-card border-r border-border flex flex-col">
<div className="flex justify-between items-center px-3 py-3 border-b border-border">
<h2 className="text-xs uppercase text-muted-foreground font-medium">Settings</h2>
<div className="flex justify-between items-center px-3 py-2.5 border-b border-border">
<h2 className="text-[10px] uppercase tracking-wider text-muted-foreground font-medium">
Settings
</h2>
<button
type="button"
onClick={handleCloseSettingsView}
className="h-6 w-6 rounded text-muted-foreground hover:text-foreground hover:bg-accent"
className="h-6 w-6 rounded text-muted-foreground hover:text-foreground hover:bg-accent transition-colors"
title="Back to conversations"
aria-label="Back to conversations"
>
@@ -943,7 +945,7 @@ export function App() {
key={section}
type="button"
className={cn(
'w-full px-3 py-2.5 text-left border-l-2 border-transparent hover:bg-accent',
'w-full px-3 py-2 text-left text-[13px] border-l-2 border-transparent hover:bg-accent transition-colors',
settingsSection === section && 'bg-accent border-l-primary'
)}
onClick={() => setSettingsSection(section)}
@@ -986,7 +988,7 @@ export function App() {
{activeConversation ? (
activeConversation.type === 'map' ? (
<>
<div className="flex justify-between items-center px-4 py-3 border-b border-border font-medium text-lg">
<div className="flex justify-between items-center px-4 py-2.5 border-b border-border font-semibold text-base">
Node Map
</div>
<div className="flex-1 overflow-hidden">
@@ -1018,7 +1020,7 @@ export function App() {
</Suspense>
) : activeConversation.type === 'raw' ? (
<>
<div className="flex justify-between items-center px-4 py-3 border-b border-border font-medium text-lg">
<div className="flex justify-between items-center px-4 py-2.5 border-b border-border font-semibold text-base">
Raw Packet Feed
</div>
<div className="flex-1 overflow-hidden">
@@ -1027,9 +1029,9 @@ export function App() {
</>
) : (
<>
<div className="flex justify-between items-center px-4 py-3 border-b border-border font-medium text-lg gap-2">
<div className="flex justify-between items-center px-4 py-2.5 border-b border-border gap-2">
<span className="flex flex-wrap items-baseline gap-x-2 min-w-0 flex-1">
<span className="flex-shrink-0">
<span className="flex-shrink-0 font-semibold text-base">
{activeConversation.type === 'channel' &&
!activeConversation.name.startsWith('#') &&
activeConversation.name !== 'Public'
@@ -1038,7 +1040,7 @@ export function App() {
{activeConversation.name}
</span>
<span
className="font-normal text-sm text-muted-foreground font-mono truncate cursor-pointer hover:text-primary"
className="font-normal text-[11px] text-muted-foreground font-mono truncate cursor-pointer hover:text-primary transition-colors"
onClick={(e) => {
e.stopPropagation();
navigator.clipboard.writeText(activeConversation.id);
@@ -1119,11 +1121,11 @@ export function App() {
) : null;
})()}
</span>
<div className="flex items-center gap-1 flex-shrink-0">
<div className="flex items-center gap-0.5 flex-shrink-0">
{/* Direct trace button (contacts only) */}
{activeConversation.type === 'contact' && (
<button
className="p-1.5 rounded hover:bg-accent text-xl leading-none"
className="p-1.5 rounded hover:bg-accent text-lg leading-none transition-colors"
onClick={handleTrace}
title="Direct Trace"
>
@@ -1134,7 +1136,7 @@ export function App() {
{(activeConversation.type === 'channel' ||
activeConversation.type === 'contact') && (
<button
className="p-1.5 rounded hover:bg-accent text-xl leading-none"
className="p-1.5 rounded hover:bg-accent text-lg leading-none transition-colors"
onClick={() =>
handleToggleFavorite(
activeConversation.type as 'channel' | 'contact',
@@ -1156,7 +1158,7 @@ export function App() {
activeConversation.type as 'channel' | 'contact',
activeConversation.id
) ? (
<span className="text-yellow-500">&#9733;</span>
<span className="text-amber-400">&#9733;</span>
) : (
<span className="text-muted-foreground">&#9734;</span>
)}
@@ -1168,7 +1170,7 @@ export function App() {
activeConversation.name === 'Public'
) && (
<button
className="p-1.5 rounded hover:bg-destructive/20 text-destructive text-xl leading-none"
className="p-1.5 rounded hover:bg-destructive/10 text-muted-foreground hover:text-destructive text-lg leading-none transition-colors"
onClick={() => {
if (activeConversation.type === 'channel') {
handleDeleteChannel(activeConversation.id);
@@ -1234,7 +1236,7 @@ export function App() {
{showSettings && (
<div className="flex-1 flex flex-col min-h-0">
<div className="flex justify-between items-center px-4 py-3 border-b border-border font-medium text-lg">
<div className="flex justify-between items-center px-4 py-2.5 border-b border-border font-semibold text-base">
<span>Radio & Settings</span>
<span className="text-sm text-muted-foreground hidden md:inline">
{SETTINGS_SECTION_LABELS[settingsSection]}

View File

@@ -170,7 +170,10 @@ export const MessageInput = forwardRef<MessageInputHandle, MessageInputProps>(fu
const showCharCounter = !isRepeaterMode && limits !== null;
return (
<form className="px-4 py-3 border-t border-border flex flex-col gap-1" onSubmit={handleSubmit}>
<form
className="px-4 py-2.5 border-t border-border flex flex-col gap-1"
onSubmit={handleSubmit}
>
<div className="flex gap-2">
<Input
ref={inputRef}

View File

@@ -461,14 +461,14 @@ export function MessageList({
<div
className={cn(
'py-1.5 px-3 rounded-lg min-w-0',
msg.outgoing ? 'bg-[#1e3a29]' : 'bg-muted'
msg.outgoing ? 'bg-msg-outgoing' : 'bg-msg-incoming'
)}
>
{showAvatar && (
<div className="text-[13px] font-bold text-foreground mb-0.5">
<div className="text-[13px] font-semibold text-foreground mb-0.5">
{canClickSender ? (
<span
className="cursor-pointer hover:text-primary hover:underline"
className="cursor-pointer hover:text-primary transition-colors"
onClick={() => onSenderClick(displaySender)}
title={`Mention ${displaySender}`}
>
@@ -587,13 +587,13 @@ export function MessageList({
{showScrollToBottom && (
<button
onClick={scrollToBottom}
className="absolute bottom-4 right-4 w-10 h-10 rounded-full bg-muted hover:bg-accent border border-border flex items-center justify-center shadow-lg transition-opacity"
className="absolute bottom-4 right-4 w-9 h-9 rounded-full bg-card hover:bg-accent border border-border flex items-center justify-center shadow-lg transition-all hover:scale-105"
title="Scroll to bottom"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="20"
height="20"
width="18"
height="18"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"

View File

@@ -1,6 +1,7 @@
import { useEffect, useRef, useMemo } from 'react';
import { MeshCoreDecoder, PayloadType, Utils } from '@michaelhart/meshcore-decoder';
import type { RawPacket } from '../types';
import { cn } from '@/lib/utils';
interface RawPacketListProps {
packets: RawPacket[];
@@ -204,9 +205,9 @@ export function RawPacketList({ packets }: RawPacketListProps) {
const sortedPackets = [...decodedPackets].sort((a, b) => a.packet.timestamp - b.packet.timestamp);
return (
<div className="h-full overflow-y-auto p-4 flex flex-col gap-3" ref={listRef}>
<div className="h-full overflow-y-auto p-4 flex flex-col gap-2" ref={listRef}>
{sortedPackets.map(({ packet, decoded }) => (
<div key={packet.id} className="py-2 px-3 bg-muted rounded">
<div key={packet.id} className="py-2 px-3 bg-card rounded-md border border-border/50">
<div className="flex items-center gap-2">
{/* Route type badge */}
<span
@@ -220,25 +221,27 @@ export function RawPacketList({ packets }: RawPacketListProps) {
{!packet.decrypted && <span title="Encrypted">🔒</span>}
{/* Summary */}
<span className={packet.decrypted ? 'text-primary' : 'text-foreground'}>
<span
className={cn('text-[13px]', packet.decrypted ? 'text-primary' : 'text-foreground')}
>
{decoded.summary}
</span>
{/* Time */}
<span className="text-muted-foreground ml-auto text-sm">
<span className="text-muted-foreground ml-auto text-[12px] tabular-nums">
{formatTime(packet.timestamp)}
</span>
</div>
{/* Signal info */}
{(packet.snr !== null || packet.rssi !== null) && (
<div className="text-[11px] text-muted-foreground mt-0.5">
<div className="text-[11px] text-muted-foreground mt-0.5 tabular-nums">
{formatSignalInfo(packet)}
</div>
)}
{/* Raw hex data (always visible) */}
<div className="font-mono text-[10px] break-all text-muted-foreground mt-1 p-1 bg-background/50 rounded">
<div className="font-mono text-[10px] break-all text-muted-foreground mt-1.5 p-1.5 bg-background/60 rounded">
{packet.data.toUpperCase()}
</div>
</div>

View File

@@ -380,9 +380,9 @@ export function Sidebar({
<div
key={row.key}
className={cn(
'px-3 py-2.5 cursor-pointer flex items-center gap-2 border-l-2 border-transparent hover:bg-accent',
'px-3 py-2 cursor-pointer flex items-center gap-2 border-l-2 border-transparent hover:bg-accent transition-colors',
isActive(row.type, row.id) && 'bg-accent border-l-primary',
row.unreadCount > 0 && '[&_.name]:font-bold [&_.name]:text-foreground'
row.unreadCount > 0 && '[&_.name]:font-semibold [&_.name]:text-foreground'
)}
onClick={() =>
handleSelectConversation({
@@ -400,14 +400,14 @@ export function Sidebar({
contactType={row.contact.type}
/>
)}
<span className="name flex-1 truncate">{row.name}</span>
<span className="name flex-1 truncate text-[13px]">{row.name}</span>
{row.unreadCount > 0 && (
<span
className={cn(
'text-[10px] font-semibold px-1.5 py-0.5 rounded-full min-w-[18px] text-center',
row.isMention
? 'bg-destructive text-destructive-foreground'
: 'bg-primary text-primary-foreground'
: 'bg-primary/90 text-primary-foreground'
)}
>
{row.unreadCount}
@@ -443,10 +443,10 @@ export function Sidebar({
const effectiveCollapsed = isSearching ? false : collapsed;
return (
<div className="flex justify-between items-center px-3 py-2 pt-3">
<div className="flex justify-between items-center px-3 py-2 pt-3.5">
<button
className={cn(
'flex items-center gap-1 text-[11px] uppercase text-muted-foreground hover:text-foreground',
'flex items-center gap-1.5 text-[10px] uppercase tracking-wider text-muted-foreground hover:text-foreground transition-colors',
isSearching && 'cursor-default'
)}
onClick={() => {
@@ -454,14 +454,14 @@ export function Sidebar({
}}
title={effectiveCollapsed ? `Expand ${title}` : `Collapse ${title}`}
>
<span className="text-[10px]">{effectiveCollapsed ? '▸' : '▾'}</span>
<span className="text-[9px]">{effectiveCollapsed ? '▸' : '▾'}</span>
<span>{title}</span>
</button>
{(showSortToggle || unreadCount > 0) && (
<div className="ml-auto flex items-center gap-1.5">
{showSortToggle && (
<button
className="bg-transparent border border-border text-muted-foreground px-1.5 py-0.5 text-[10px] rounded hover:bg-accent hover:text-foreground mr-0.5"
className="bg-transparent text-muted-foreground/60 px-1 py-0.5 text-[10px] rounded hover:text-foreground transition-colors"
onClick={handleSortToggle}
title={sortOrder === 'alpha' ? 'Sort by recent' : 'Sort alphabetically'}
>
@@ -469,7 +469,7 @@ export function Sidebar({
</button>
)}
{unreadCount > 0 && (
<span className="text-[10px] font-medium px-1.5 py-0.5 rounded-full bg-muted text-muted-foreground">
<span className="text-[10px] font-medium px-1.5 py-0.5 rounded-full bg-secondary text-muted-foreground">
{unreadCount}
</span>
)}
@@ -482,31 +482,33 @@ export function Sidebar({
return (
<div className="sidebar w-60 h-full min-h-0 bg-card border-r border-border flex flex-col">
{/* Header */}
<div className="flex justify-between items-center px-3 py-3 border-b border-border">
<h2 className="text-xs uppercase text-muted-foreground font-medium">Conversations</h2>
<div className="flex justify-between items-center px-3 py-2.5 border-b border-border">
<h2 className="text-[10px] uppercase tracking-wider text-muted-foreground font-medium">
Conversations
</h2>
<Button
variant="ghost"
size="sm"
onClick={onNewMessage}
title="New Message"
className="h-6 w-6 p-0 text-muted-foreground hover:text-foreground"
className="h-6 w-6 p-0 text-muted-foreground hover:text-foreground transition-colors"
>
+
</Button>
</div>
{/* Search */}
<div className="relative px-3 py-2 border-b border-border">
<div className="relative px-3 py-2">
<Input
type="text"
placeholder="Search..."
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
className="h-8 text-sm pr-8"
className="h-7 text-[13px] pr-8 bg-background/50"
/>
{searchQuery && (
<button
className="absolute right-4 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground text-lg leading-none"
className="absolute right-4 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground text-lg leading-none transition-colors"
onClick={() => setSearchQuery('')}
title="Clear search"
>
@@ -521,7 +523,7 @@ export function Sidebar({
{!query && (
<div
className={cn(
'px-3 py-2.5 cursor-pointer flex items-center gap-2 border-l-2 border-transparent hover:bg-accent',
'px-3 py-2 cursor-pointer flex items-center gap-2 border-l-2 border-transparent hover:bg-accent transition-colors text-[13px]',
isActive('raw', 'raw') && 'bg-accent border-l-primary'
)}
onClick={() =>
@@ -533,7 +535,7 @@ export function Sidebar({
}
>
<span className="text-muted-foreground text-xs">📡</span>
<span className="flex-1 truncate">Packet Feed</span>
<span className="flex-1 truncate text-muted-foreground">Packet Feed</span>
</div>
)}
@@ -541,7 +543,7 @@ export function Sidebar({
{!query && (
<div
className={cn(
'px-3 py-2.5 cursor-pointer flex items-center gap-2 border-l-2 border-transparent hover:bg-accent',
'px-3 py-2 cursor-pointer flex items-center gap-2 border-l-2 border-transparent hover:bg-accent transition-colors text-[13px]',
isActive('map', 'map') && 'bg-accent border-l-primary'
)}
onClick={() =>
@@ -553,7 +555,7 @@ export function Sidebar({
}
>
<span className="text-muted-foreground text-xs">🗺</span>
<span className="flex-1 truncate">Node Map</span>
<span className="flex-1 truncate text-muted-foreground">Node Map</span>
</div>
)}
@@ -561,7 +563,7 @@ export function Sidebar({
{!query && (
<div
className={cn(
'px-3 py-2.5 cursor-pointer flex items-center gap-2 border-l-2 border-transparent hover:bg-accent',
'px-3 py-2 cursor-pointer flex items-center gap-2 border-l-2 border-transparent hover:bg-accent transition-colors text-[13px]',
isActive('visualizer', 'visualizer') && 'bg-accent border-l-primary'
)}
onClick={() =>
@@ -573,7 +575,7 @@ export function Sidebar({
}
>
<span className="text-muted-foreground text-xs"></span>
<span className="flex-1 truncate">Mesh Visualizer</span>
<span className="flex-1 truncate text-muted-foreground">Mesh Visualizer</span>
</div>
)}
@@ -581,18 +583,18 @@ export function Sidebar({
{!query && (
<div
className={cn(
'px-3 py-2.5 cursor-pointer flex items-center gap-2 border-l-2 border-transparent hover:bg-accent',
'px-3 py-2 cursor-pointer flex items-center gap-2 border-l-2 border-transparent hover:bg-accent transition-colors text-[13px]',
showCracker && 'bg-accent border-l-primary'
)}
onClick={onToggleCracker}
>
<span className="text-muted-foreground text-xs">🔓</span>
<span className="flex-1 truncate">
<span className="flex-1 truncate text-muted-foreground">
{showCracker ? 'Hide' : 'Show'} Room Finder
<span
className={cn(
'ml-1 text-xs',
crackerRunning ? 'text-green-500' : 'text-muted-foreground'
'ml-1 text-[11px]',
crackerRunning ? 'text-primary' : 'text-muted-foreground'
)}
>
({crackerRunning ? 'running' : 'idle'})
@@ -604,7 +606,7 @@ export function Sidebar({
{/* Mark All Read */}
{!query && Object.keys(unreadCounts).length > 0 && (
<div
className="px-3 py-2.5 cursor-pointer flex items-center gap-2 border-l-2 border-transparent hover:bg-accent"
className="px-3 py-2 cursor-pointer flex items-center gap-2 border-l-2 border-transparent hover:bg-accent transition-colors text-[13px]"
onClick={onMarkAllRead}
>
<span className="text-muted-foreground text-xs"></span>

View File

@@ -3,6 +3,7 @@ import { Menu } from 'lucide-react';
import type { HealthStatus, RadioConfig } from '../types';
import { api } from '../api';
import { toast } from './ui/sonner';
import { cn } from '@/lib/utils';
interface StatusBarProps {
health: HealthStatus | null;
@@ -39,34 +40,39 @@ export function StatusBar({
};
return (
<div className="flex items-center gap-4 px-4 py-2 bg-card border-b border-border text-xs">
<div className="flex items-center gap-3 px-4 py-2.5 bg-card border-b border-border text-xs">
{/* Mobile menu button - only visible on small screens */}
{onMenuClick && (
<button
onClick={onMenuClick}
className="md:hidden p-1 bg-transparent border-none text-foreground cursor-pointer"
className="md:hidden p-1 bg-transparent border-none text-muted-foreground hover:text-foreground cursor-pointer transition-colors"
aria-label="Open menu"
>
<Menu className="h-5 w-5" />
</button>
)}
<h1 className="text-base font-semibold mr-auto">RemoteTerm</h1>
<h1 className="text-sm font-semibold tracking-tight mr-auto text-foreground">RemoteTerm</h1>
<div className="flex items-center gap-1 text-muted-foreground">
<div className="flex items-center gap-1.5">
<div
className={`w-2 h-2 rounded-full ${connected ? 'bg-primary' : 'bg-muted-foreground'}`}
className={cn(
'w-2 h-2 rounded-full transition-colors',
connected
? 'bg-primary shadow-[0_0_6px_hsl(var(--primary)/0.5)]'
: 'bg-muted-foreground'
)}
/>
<span className="hidden lg:inline text-foreground">
<span className="hidden lg:inline text-muted-foreground">
{connected ? 'Connected' : 'Disconnected'}
</span>
</div>
{config && (
<div className="hidden lg:flex items-center gap-2 text-muted-foreground">
<span className="text-foreground">{config.name || 'Unnamed'}</span>
<span className="text-foreground font-medium">{config.name || 'Unnamed'}</span>
<span
className="font-mono text-muted-foreground cursor-pointer hover:text-primary"
className="font-mono text-[11px] text-muted-foreground cursor-pointer hover:text-primary transition-colors"
onClick={() => {
navigator.clipboard.writeText(config.public_key);
toast.success('Public key copied!');
@@ -82,19 +88,16 @@ export function StatusBar({
<button
onClick={handleReconnect}
disabled={reconnecting}
className="px-3 py-1 bg-amber-950 border border-amber-800 text-amber-400 rounded text-xs cursor-pointer hover:bg-amber-900 disabled:opacity-50 disabled:cursor-not-allowed"
className="px-3 py-1 bg-amber-500/10 border border-amber-500/20 text-amber-400 rounded-md text-xs cursor-pointer hover:bg-amber-500/15 transition-colors disabled:opacity-50 disabled:cursor-not-allowed"
>
{reconnecting ? 'Reconnecting...' : 'Reconnect'}
</button>
)}
<button
onClick={onSettingsClick}
className="px-3 py-1 bg-secondary border border-border text-foreground rounded text-xs cursor-pointer hover:bg-accent"
className="px-3 py-1.5 bg-secondary border border-border text-muted-foreground rounded-md text-xs cursor-pointer hover:bg-accent hover:text-foreground transition-colors"
>
<span role="img" aria-label="Settings">
&#128295;
</span>{' '}
{settingsMode ? 'Back to Chat' : 'Radio & Config'}
{settingsMode ? 'Back to Chat' : 'Settings'}
</button>
</div>
);

View File

@@ -4,26 +4,30 @@
@layer base {
:root {
--background: 0 0% 10%;
--foreground: 0 0% 88%;
--card: 0 0% 14%;
--card-foreground: 0 0% 88%;
--popover: 0 0% 14%;
--popover-foreground: 0 0% 88%;
--primary: 122 39% 49%;
--background: 224 14% 8%;
--foreground: 213 15% 90%;
--card: 224 13% 11%;
--card-foreground: 213 15% 90%;
--popover: 224 13% 12%;
--popover-foreground: 213 15% 90%;
--primary: 152 60% 38%;
--primary-foreground: 0 0% 100%;
--secondary: 0 0% 20%;
--secondary-foreground: 0 0% 88%;
--muted: 0 0% 20%;
--muted-foreground: 0 0% 64%;
--accent: 0 0% 20%;
--accent-foreground: 0 0% 88%;
--destructive: 0 62% 50%;
--secondary: 224 12% 17%;
--secondary-foreground: 213 12% 85%;
--muted: 224 12% 15%;
--muted-foreground: 218 10% 60%;
--accent: 224 11% 19%;
--accent-foreground: 213 15% 90%;
--destructive: 0 72% 51%;
--destructive-foreground: 0 0% 100%;
--border: 0 0% 20%;
--input: 0 0% 20%;
--ring: 122 39% 49%;
--border: 224 11% 17%;
--input: 224 11% 17%;
--ring: 152 60% 38%;
--radius: 0.5rem;
/* Semantic colors for specific contexts */
--msg-outgoing: 152 30% 14%;
--msg-incoming: 224 12% 15%;
}
}
@@ -33,11 +37,40 @@
}
body {
@apply bg-background text-foreground;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
font-family:
system-ui,
-apple-system,
BlinkMacSystemFont,
'Segoe UI',
sans-serif;
font-size: 14px;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
}
/* Custom scrollbar — thin, unobtrusive, matches palette */
::-webkit-scrollbar {
width: 6px;
height: 6px;
}
::-webkit-scrollbar-track {
background: transparent;
}
::-webkit-scrollbar-thumb {
background: hsl(224 11% 22%);
border-radius: 3px;
}
::-webkit-scrollbar-thumb:hover {
background: hsl(224 11% 28%);
}
/* Firefox scrollbar */
* {
scrollbar-width: thin;
scrollbar-color: hsl(224 11% 22%) transparent;
}
/* Constrain CodeMirror editor width */
.cm-editor {
max-width: 100% !important;

View File

@@ -32,7 +32,12 @@ body,
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
font-family:
system-ui,
-apple-system,
BlinkMacSystemFont,
'Segoe UI',
sans-serif;
/* Prevent overscroll/bounce on mobile */
overscroll-behavior: none;
padding: var(--safe-area-top) var(--safe-area-right) var(--safe-area-bottom-capped)

View File

@@ -41,6 +41,8 @@ export default {
DEFAULT: "hsl(var(--card))",
foreground: "hsl(var(--card-foreground))",
},
"msg-outgoing": "hsl(var(--msg-outgoing))",
"msg-incoming": "hsl(var(--msg-incoming))",
},
borderRadius: {
lg: "var(--radius)",