mirror of
https://github.com/hansjone/netx.git
synced 2026-10-09 08:10:47 +08:00
Improve topology canvas UX and vendor NE icons.
Replace the top selection bar with a context menu, tighten map/palette cards and fullscreen controls, and tint the router asset by vendor (ZTE keeps default blue). Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
658c19e457
commit
2f1c33924e
5 changed files with 656 additions and 294 deletions
|
|
@ -688,23 +688,30 @@ pre {
|
|||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.app-main .help-hint__trigger,
|
||||
.help-hint__trigger {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
padding: 0;
|
||||
border: 1px solid #cbd5e1;
|
||||
border-radius: 50%;
|
||||
background: #f8fafc;
|
||||
width: auto;
|
||||
height: auto;
|
||||
min-width: 0;
|
||||
padding: 0 2px;
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
background: transparent;
|
||||
box-shadow: none;
|
||||
color: #64748b;
|
||||
font-size: 12px;
|
||||
font-size: 13px;
|
||||
font-weight: 700;
|
||||
line-height: 1;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.app-main .help-hint__trigger:hover,
|
||||
.app-main .help-hint__trigger:focus-visible,
|
||||
.help-hint__trigger:hover,
|
||||
.help-hint__trigger:focus-visible {
|
||||
border-color: #1565c0;
|
||||
border: none;
|
||||
background: transparent;
|
||||
box-shadow: none;
|
||||
color: #1565c0;
|
||||
outline: none;
|
||||
}
|
||||
|
|
@ -1931,6 +1938,7 @@ pre {
|
|||
flex-direction: column;
|
||||
gap: 8px;
|
||||
min-height: 0;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.topo-sidebar__section--grow {
|
||||
|
|
@ -1983,28 +1991,84 @@ pre {
|
|||
padding: 0;
|
||||
overflow: auto;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.topo-map-list li {
|
||||
.topo-map-list li,
|
||||
.topo-palette > li {
|
||||
margin: 0 0 6px;
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.topo-map-list li:last-child,
|
||||
.topo-palette > li:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.topo-map-list__row,
|
||||
.topo-palette__row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
align-items: stretch;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 8px;
|
||||
background: #fff;
|
||||
overflow: hidden;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.topo-map-list li.is-active {
|
||||
.topo-map-list li.is-active .topo-map-list__row {
|
||||
border-color: #93c5fd;
|
||||
background: #e8f1fb;
|
||||
}
|
||||
|
||||
.topo-palette > li.is-on-canvas .topo-palette__row {
|
||||
background: #f8fafc;
|
||||
border-color: #e2e8f0;
|
||||
}
|
||||
|
||||
.topo-map-list__item,
|
||||
.topo-palette__item {
|
||||
flex: 1;
|
||||
display: block;
|
||||
flex: 1 1 auto;
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
text-align: left;
|
||||
border: 0;
|
||||
background: transparent;
|
||||
padding: 8px;
|
||||
padding: 8px 10px;
|
||||
cursor: pointer;
|
||||
border-radius: 8px;
|
||||
border-radius: 0;
|
||||
min-width: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.app-main .topo-map-list__item,
|
||||
.app-main .topo-map-list__icon,
|
||||
.app-main .topo-palette__item {
|
||||
border: none;
|
||||
background: transparent;
|
||||
border-radius: 0;
|
||||
box-shadow: none;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.app-main .topo-map-list__item,
|
||||
.app-main .topo-palette__item {
|
||||
display: block;
|
||||
width: 100%;
|
||||
padding: 8px 10px;
|
||||
}
|
||||
|
||||
.app-main .topo-map-list__icon {
|
||||
width: 32px;
|
||||
height: auto;
|
||||
padding: 0;
|
||||
color: #64748b;
|
||||
font-size: 14px;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.topo-map-list__item:hover,
|
||||
|
|
@ -2012,6 +2076,43 @@ pre {
|
|||
background: #f1f5f9;
|
||||
}
|
||||
|
||||
.topo-map-list li.is-active .topo-map-list__item:hover {
|
||||
background: #dbeafe;
|
||||
}
|
||||
|
||||
.topo-map-list__actions {
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
flex: 0 0 auto;
|
||||
border-left: 1px solid #e2e8f0;
|
||||
}
|
||||
|
||||
.topo-map-list li.is-active .topo-map-list__actions {
|
||||
border-left-color: #bfdbfe;
|
||||
}
|
||||
|
||||
.topo-map-list__icon {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 32px;
|
||||
min-height: 100%;
|
||||
border: 0;
|
||||
background: transparent;
|
||||
color: #64748b;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.topo-map-list__icon:hover:not(:disabled) {
|
||||
background: #f1f5f9;
|
||||
color: #0f172a;
|
||||
}
|
||||
|
||||
.topo-map-list__icon:disabled {
|
||||
opacity: 0.45;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.topo-palette__item:disabled {
|
||||
opacity: 0.55;
|
||||
cursor: default;
|
||||
|
|
@ -2019,6 +2120,8 @@ pre {
|
|||
|
||||
.topo-palette__empty {
|
||||
padding: 8px;
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.topo-map-list__name,
|
||||
|
|
@ -2026,6 +2129,9 @@ pre {
|
|||
display: block;
|
||||
font-weight: 600;
|
||||
color: #0f172a;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.topo-map-list__meta,
|
||||
|
|
@ -2033,6 +2139,9 @@ pre {
|
|||
display: block;
|
||||
font-size: 12px;
|
||||
color: #64748b;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.topo-main {
|
||||
|
|
@ -2048,18 +2157,21 @@ pre {
|
|||
|
||||
.topo-toolbar {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
padding: 10px 12px;
|
||||
padding: 8px 12px;
|
||||
border-bottom: 1px solid #e2e8f0;
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
|
||||
.topo-toolbar__left {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
min-width: 0;
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
|
||||
.topo-toolbar__title {
|
||||
|
|
@ -2069,16 +2181,23 @@ pre {
|
|||
min-width: 0;
|
||||
}
|
||||
|
||||
.topo-toolbar__title strong {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.topo-toolbar__actions {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
flex-wrap: nowrap;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.topo-display-toggles {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
flex-wrap: nowrap;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
margin-right: 4px;
|
||||
|
|
@ -2095,20 +2214,49 @@ pre {
|
|||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.topo-selection {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
padding: 8px 12px;
|
||||
background: #f8fafc;
|
||||
border-bottom: 1px solid #e2e8f0;
|
||||
.topo-ctx {
|
||||
position: fixed;
|
||||
z-index: 40;
|
||||
min-width: 168px;
|
||||
padding: 4px 0;
|
||||
margin: 0;
|
||||
list-style: none;
|
||||
background: #0f172a;
|
||||
color: #e2e8f0;
|
||||
border: 1px solid #334155;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 10px 28px rgba(15, 23, 42, 0.28);
|
||||
}
|
||||
|
||||
.topo-selection__actions {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
.topo-ctx__item {
|
||||
display: block;
|
||||
width: 100%;
|
||||
padding: 8px 14px;
|
||||
border: 0;
|
||||
background: transparent;
|
||||
color: inherit;
|
||||
text-align: left;
|
||||
font: inherit;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.topo-ctx__item:hover:not(:disabled) {
|
||||
background: #1e293b;
|
||||
}
|
||||
|
||||
.topo-ctx__item:disabled {
|
||||
opacity: 0.45;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.topo-ctx__item--danger:hover:not(:disabled) {
|
||||
background: #7f1d1d;
|
||||
}
|
||||
|
||||
.topo-ctx__sep {
|
||||
height: 1px;
|
||||
margin: 4px 0;
|
||||
background: #334155;
|
||||
}
|
||||
|
||||
.topo-discover {
|
||||
|
|
@ -2197,6 +2345,29 @@ pre {
|
|||
position: relative;
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.topo-canvas:fullscreen,
|
||||
.topo-canvas.is-fullscreen:fullscreen {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
/* Place fullscreen above zoom-in (+); Controls renders custom children last. */
|
||||
.topo-canvas .react-flow__controls {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.topo-canvas .react-flow__controls-button.topo-fs-control {
|
||||
order: -1;
|
||||
}
|
||||
|
||||
.topo-canvas .react-flow__controls-button.topo-fs-control svg {
|
||||
max-width: 14px;
|
||||
max-height: 14px;
|
||||
}
|
||||
|
||||
.topo-canvas__empty {
|
||||
|
|
@ -2215,17 +2386,43 @@ pre {
|
|||
box-shadow: none;
|
||||
font-size: 11px;
|
||||
text-align: center;
|
||||
--topo-vendor: #64748b;
|
||||
/* Default asset is blue (= ZTE). */
|
||||
--topo-vendor: #0277bd;
|
||||
--topo-icon-filter: none;
|
||||
}
|
||||
|
||||
.topo-node--cisco { --topo-vendor: #1d4ed8; }
|
||||
.topo-node--huawei { --topo-vendor: #c62828; }
|
||||
.topo-node--zte { --topo-vendor: #0277bd; }
|
||||
.topo-node--juniper { --topo-vendor: #2e7d32; }
|
||||
.topo-node--nokia { --topo-vendor: #00838f; }
|
||||
.topo-node--ericsson { --topo-vendor: #f9a825; }
|
||||
.topo-node--h3c { --topo-vendor: #ef6c00; }
|
||||
.topo-node--other { --topo-vendor: #546e7a; }
|
||||
.topo-node--cisco {
|
||||
--topo-vendor: #1d4ed8;
|
||||
--topo-icon-filter: hue-rotate(-8deg) saturate(1.15);
|
||||
}
|
||||
.topo-node--huawei {
|
||||
--topo-vendor: #c62828;
|
||||
--topo-icon-filter: hue-rotate(155deg) saturate(1.35);
|
||||
}
|
||||
.topo-node--zte {
|
||||
--topo-vendor: #0277bd;
|
||||
--topo-icon-filter: none;
|
||||
}
|
||||
.topo-node--juniper {
|
||||
--topo-vendor: #2e7d32;
|
||||
--topo-icon-filter: hue-rotate(95deg) saturate(1.2);
|
||||
}
|
||||
.topo-node--nokia {
|
||||
--topo-vendor: #00838f;
|
||||
--topo-icon-filter: hue-rotate(-28deg) saturate(1.1) brightness(0.98);
|
||||
}
|
||||
.topo-node--ericsson {
|
||||
--topo-vendor: #f9a825;
|
||||
--topo-icon-filter: hue-rotate(175deg) saturate(1.45) brightness(1.05);
|
||||
}
|
||||
.topo-node--h3c {
|
||||
--topo-vendor: #ef6c00;
|
||||
--topo-icon-filter: hue-rotate(165deg) saturate(1.4);
|
||||
}
|
||||
.topo-node--other {
|
||||
--topo-vendor: #546e7a;
|
||||
--topo-icon-filter: grayscale(0.85) brightness(0.95);
|
||||
}
|
||||
|
||||
.topo-node__glyph {
|
||||
position: relative;
|
||||
|
|
@ -2252,14 +2449,20 @@ pre {
|
|||
transform: translate(-50%, -50%) !important;
|
||||
}
|
||||
|
||||
.topo-node.is-selected .topo-node__icon-body {
|
||||
stroke: #0f172a;
|
||||
stroke-width: 1.6;
|
||||
.topo-node.is-selected .topo-node__glyph {
|
||||
outline: 2px solid #2563eb;
|
||||
outline-offset: 5px;
|
||||
border-radius: 999px;
|
||||
}
|
||||
|
||||
.topo-node.is-selected .topo-node__icon {
|
||||
transform: scale(1.08);
|
||||
filter: var(--topo-icon-filter, none) drop-shadow(0 0 8px rgba(37, 99, 235, 0.55));
|
||||
}
|
||||
|
||||
.topo-node.is-selected .topo-node__caption {
|
||||
color: #0f172a;
|
||||
font-weight: 600;
|
||||
color: #1d4ed8;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.topo-node__icon {
|
||||
|
|
@ -2267,30 +2470,11 @@ pre {
|
|||
width: 56px;
|
||||
height: 56px;
|
||||
margin: 0;
|
||||
object-fit: contain;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.topo-node__icon-shadow {
|
||||
fill: rgba(15, 23, 42, 0.28);
|
||||
}
|
||||
|
||||
.topo-node__icon-rim {
|
||||
fill: color-mix(in srgb, var(--topo-vendor, #64748b) 70%, #0f172a);
|
||||
}
|
||||
|
||||
.topo-node__icon-body {
|
||||
fill: var(--topo-vendor, #64748b);
|
||||
stroke: color-mix(in srgb, var(--topo-vendor, #64748b) 45%, #0f172a);
|
||||
stroke-width: 1;
|
||||
}
|
||||
|
||||
.topo-node__icon-face {
|
||||
fill: color-mix(in srgb, var(--topo-vendor, #64748b) 62%, #cbd5e1);
|
||||
}
|
||||
|
||||
.topo-node__icon-arrows {
|
||||
fill: #ffffff;
|
||||
stroke: none;
|
||||
user-select: none;
|
||||
filter: var(--topo-icon-filter, none);
|
||||
transition: transform 0.12s ease, filter 0.12s ease;
|
||||
}
|
||||
|
||||
/* Same plain-text style as edge port labels */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue