spaxel/dashboard/css/quick-actions.css
jedarden 5707a89ad5 fix(dashboard): repair CSS syntax errors and complete token migration
Fix systemic missing-colon bugs in layout.css where property values
like top, left, right, bottom, gap, padding were directly followed by
var() without a colon separator. This broke all fixed-position panels
in the live view. Also add missing --space-half token to tokens.css
and complete design token migration across remaining CSS files.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-24 16:57:32 -04:00

294 lines
6.3 KiB
CSS

/**
* Spaxel Dashboard - Spatial Quick Actions Styles
*
* Right-click (desktop) or long-press (mobile) context menus
* on 3D elements for context-sensitive actions.
*/
/* ===== Context Menu Container ===== */
.context-menu {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 1000;
display: none;
}
.context-menu.visible {
display: block;
}
.context-backdrop {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: var(--shadow-lg);
backdrop-filter: blur(2px);
-webkit-backdrop-filter: blur(2px);
animation: fadeIn 0.15s ease-out;
}
/* ===== Safe Area Insets for iOS ===== */
@supports (padding: max(0px)) {
.context-menu {
/* Respect safe area insets for notched devices */
padding-top: env(safe-area-inset-top);
padding-bottom: env(safe-area-inset-bottom);
padding-left: env(safe-area-inset-left);
padding-right: env(safe-area-inset-right);
}
.follow-mode-indicator {
/* Adjust bottom position to account for safe area */
bottom: calc(80px + env(safe-area-inset-bottom));
}
@media (max-width: 600px) {
.follow-mode-indicator {
bottom: calc(100px + env(safe-area-inset-bottom));
}
}
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
/* ===== Context Container ===== */
.context-container {
position: absolute;
min-width: 280px;
max-width: 340px;
background: var(--context-bg, var(--bg-card));
border-radius: var(--radius-card);
box-shadow: 0 8px 32px var(--shadow-xl);
border: 1px solid var(--context-border, var(--bg-hover));
display: flex;
flex-direction: column;
overflow: hidden;
animation: scaleIn 0.15s ease-out;
}
@keyframes scaleIn {
from {
opacity: 0;
transform: scale(0.95);
}
to {
opacity: 1;
transform: scale(1);
}
}
/* ===== Context Header ===== */
.context-header {
display: flex;
align-items: center;
gap: var(--space-3);
padding: 14px var(--space-4);
border-bottom: 1px solid var(--context-border, var(--bg-hover));
background: var(--context-header-bg, var(--border-subtle));
}
.context-icon {
font-size: 22px;
flex-shrink: 0;
width: 32px;
height: 32px;
display: flex;
align-items: center;
justify-content: center;
background: var(--context-icon-bg, var(--blue-muted));
border-radius: var(--radius-card);
}
.context-title {
flex: 1;
font-size: var(--text-md);
font-weight: 600;
color: var(--context-text, var(--slate-12));
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
/* ===== Context Body ===== */
.context-body {
max-height: 400px;
overflow-y: auto;
overflow-x: hidden;
}
.context-body::-webkit-scrollbar {
width: 6px;
}
.context-body::-webkit-scrollbar-track {
background: transparent;
}
.context-body::-webkit-scrollbar-thumb {
background: var(--border-strong);
border-radius: var(--radius-control);
}
.context-body::-webkit-scrollbar-thumb:hover {
background: var(--slate-7);
}
/* ===== Context Items ===== */
.context-item {
display: flex;
align-items: flex-start;
gap: var(--space-3);
padding: var(--space-3) var(--space-4);
cursor: pointer;
transition: background 0.15s ease;
border-left: 3px solid transparent;
}
.context-item:hover {
background: var(--context-hover, var(--border-subtle));
}
.context-item:active {
background: var(--context-active, var(--border-default));
}
.item-icon {
font-size: var(--text-xl);
flex-shrink: 0;
width: 24px;
text-align: center;
padding-top: var(--space-half);
}
.item-content {
flex: 1;
min-width: 0;
}
.item-label {
font-size: var(--text-sm);
font-weight: 500;
color: var(--context-text, var(--slate-12));
margin-bottom: var(--space-half);
}
.item-description {
font-size: var(--text-xs);
color: var(--context-description, var(--text-muted));
line-height: 1.3;
}
/* ===== Target-Specific Styling ===== */
/* Blob/Person context */
.context-menu[data-target="blob"] .context-icon {
background: var(--blue-muted);
color: var(--blue-10);
}
/* Node context */
.context-menu[data-target="node"] .context-icon {
background: var(--ok-bg);
color: var(--ok);
}
/* Zone context */
.context-menu[data-target="zone"] .context-icon {
background: var(--warn-bg);
color: var(--warn);
}
/* Empty space context */
.context-menu[data-target="empty"] .context-icon {
background: var(--bg-active);
color: var(--slate-10);
}
/* Portal context */
.context-menu[data-target="portal"] .context-icon {
background: var(--blue-muted);
color: var(--blue-8);
}
/* Trigger context */
.context-menu[data-target="trigger"] .context-icon {
background: var(--alert-bg);
color: var(--alert);
}
/* ===== Follow Mode Indicator ===== */
.follow-mode-indicator {
position: fixed;
bottom: 80px;
left: 50%;
transform: translateX(-50%);
background: var(--blue-10);
color: var(--text-on-accent);
padding: 10px var(--space-5);
border-radius: var(--radius-modal);
font-size: var(--text-sm);
font-weight: 500;
display: flex;
align-items: center;
gap: var(--space-2);
z-index: 999;
animation: slideUp 0.2s ease-out;
pointer-events: none;
}
.follow-mode-indicator::before {
content: '🎯';
}
@keyframes slideUp {
from {
opacity: 0;
transform: translate(-50%, 20px);
}
to {
opacity: 1;
transform: translate(-50%, 0);
}
}
/* ===== Responsive Design ===== */
@media (max-width: 600px) {
.context-container {
min-width: 260px;
max-width: 90vw;
}
.context-item {
padding: 14px var(--space-4);
}
.follow-mode-indicator {
bottom: 100px;
padding: var(--space-3) var(--space-6);
font-size: var(--text-md);
}
}
/* ===== Accessibility ===== */
.context-item:focus-visible {
outline: 2px solid var(--context-accent, var(--blue-10));
outline-offset: -2px;
}
/* ===== Reduced Motion ===== */
@media (prefers-reduced-motion: reduce) {
.context-menu * {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}