sync: contextual substrate UX from private repo

- Add DimensionIconsContext for app-wide dimension icon sharing
- Enhanced getNodeIcon() with favicon/YouTube/PDF detection + dimension icons
- Propagate dynamic icons to GridView, ListView, SearchModal, FocusPanel, ViewsOverlay, FolderViewOverlay
- Add RahEdge component with hover labels for map edges
- Update RahNode with dimension-colored borders and icon support
- Add MiniMap with dimension color coding to MapPane
- MCP server: add description field to rah_update_node, bump standalone to v1.4.2

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
“BeeRad”
2026-02-15 08:55:47 +11:00
co-authored by Claude Opus 4.6
parent d6987a3dc1
commit d723212ed3
17 changed files with 492 additions and 53 deletions
+8 -7
View File
@@ -7,6 +7,7 @@ import ConfirmDialog from '../common/ConfirmDialog';
import InputDialog from '../common/InputDialog';
import { getNodeIcon } from '@/utils/nodeIcons';
import LucideIconPicker, { DynamicIcon } from '../common/LucideIconPicker';
import { useDimensionIcons } from '@/context/DimensionIconsContext';
import { usePersistentState } from '@/hooks/usePersistentState';
type DimensionViewMode = 'grid' | 'list' | 'kanban';
@@ -121,8 +122,8 @@ export default function FolderViewOverlay({ onClose, onNodeOpen, refreshToken, o
// Node priority ordering within dimensions (persisted)
const [dimensionOrders, setDimensionOrders] = usePersistentState<Record<string, number[]>>('ui.dimensionOrders', {});
// Dimension icons (persisted) - maps dimension name to Lucide icon name
const [dimensionIcons, setDimensionIcons] = usePersistentState<Record<string, string>>('ui.dimensionIcons', {});
// Dimension icons from shared context
const { dimensionIcons, setDimensionIcons } = useDimensionIcons();
// Dimension edit modal state
const [editingDimensionModal, setEditingDimensionModal] = useState<DimensionSummary | null>(null);
@@ -1235,7 +1236,7 @@ export default function FolderViewOverlay({ onClose, onNodeOpen, refreshToken, o
</div>
{node.link && (
<span style={{ flexShrink: 0 }}>
{getNodeIcon(node)}
{getNodeIcon(node, dimensionIcons)}
</span>
)}
</div>
@@ -1359,7 +1360,7 @@ export default function FolderViewOverlay({ onClose, onNodeOpen, refreshToken, o
borderRadius: '8px',
flexShrink: 0
}}>
{getNodeIcon(node)}
{getNodeIcon(node, dimensionIcons)}
</div>
<div style={{ flex: 1, minWidth: 0 }}>
@@ -1829,7 +1830,7 @@ export default function FolderViewOverlay({ onClose, onNodeOpen, refreshToken, o
borderRadius: '8px',
flexShrink: 0
}}>
{getNodeIcon(node)}
{getNodeIcon(node, dimensionIcons)}
</div>
<div style={{ flex: 1, minWidth: 0 }}>
@@ -2560,7 +2561,7 @@ export default function FolderViewOverlay({ onClose, onNodeOpen, refreshToken, o
justifyContent: 'center',
flexShrink: 0
}}>
{getNodeIcon(node)}
{getNodeIcon(node, dimensionIcons)}
</div>
<div style={{ flex: 1, minWidth: 0 }}>
<div style={{
@@ -2848,7 +2849,7 @@ export default function FolderViewOverlay({ onClose, onNodeOpen, refreshToken, o
}}>
#{node.id}
</span>
<span style={{ flexShrink: 0, marginTop: '1px' }}>{getNodeIcon(node)}</span>
<span style={{ flexShrink: 0, marginTop: '1px' }}>{getNodeIcon(node, dimensionIcons)}</span>
<div style={{
fontSize: '12px',
fontWeight: 500,