refactor(nav): reorganize sidebar with dynamic sections at top
- move runs and sessions to top of navigation (most dynamic) - add visual separator between dynamic and configuration sections - reorder remaining items: scenarios, snippets, credentials, environments - implement separator component in nav rendering logic
This commit is contained in:
@@ -95,6 +95,12 @@
|
|||||||
background: var(--color-secondary-hover);
|
background: var(--color-secondary-hover);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.navSeparator {
|
||||||
|
height: var(--border-width);
|
||||||
|
background: var(--color-border);
|
||||||
|
margin: var(--space-2) var(--space-2);
|
||||||
|
}
|
||||||
|
|
||||||
.main {
|
.main {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
|||||||
+26
-18
@@ -90,13 +90,17 @@ const SnippetDetailPage = lazy(() =>
|
|||||||
import('./pages/snippet/SnippetDetailPage').then((m) => ({ default: m.SnippetDetailPage })),
|
import('./pages/snippet/SnippetDetailPage').then((m) => ({ default: m.SnippetDetailPage })),
|
||||||
);
|
);
|
||||||
|
|
||||||
const NAV: { path: string; labelKey: string; Icon: LucideIcon }[] = [
|
const NAV: (
|
||||||
{ path: '/environments', labelKey: 'nav.environments', Icon: Globe },
|
| { path: string; labelKey: string; Icon: LucideIcon }
|
||||||
{ path: '/credentials', labelKey: 'nav.credentials', Icon: KeyRound },
|
| { separator: true }
|
||||||
{ path: '/snippets', labelKey: 'nav.snippets', Icon: Braces },
|
)[] = [
|
||||||
{ path: '/sessions', labelKey: 'nav.sessions', Icon: Monitor },
|
|
||||||
{ path: '/scenarios', labelKey: 'nav.scenarios', Icon: ClipboardList },
|
|
||||||
{ path: '/runs', labelKey: 'nav.runs', Icon: Activity },
|
{ path: '/runs', labelKey: 'nav.runs', Icon: Activity },
|
||||||
|
{ path: '/sessions', labelKey: 'nav.sessions', Icon: Monitor },
|
||||||
|
{ separator: true },
|
||||||
|
{ path: '/scenarios', labelKey: 'nav.scenarios', Icon: ClipboardList },
|
||||||
|
{ path: '/snippets', labelKey: 'nav.snippets', Icon: Braces },
|
||||||
|
{ path: '/credentials', labelKey: 'nav.credentials', Icon: KeyRound },
|
||||||
|
{ path: '/environments', labelKey: 'nav.environments', Icon: Globe },
|
||||||
];
|
];
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
@@ -114,18 +118,22 @@ export default function App() {
|
|||||||
>
|
>
|
||||||
<div className={styles.sideContent}>
|
<div className={styles.sideContent}>
|
||||||
<nav className={styles.nav}>
|
<nav className={styles.nav}>
|
||||||
{NAV.map(({ path, labelKey, Icon }) => (
|
{NAV.map((item, index) =>
|
||||||
<NavLink
|
'separator' in item ? (
|
||||||
key={path}
|
<div key={`separator-${index}`} className={styles.navSeparator} />
|
||||||
to={path}
|
) : (
|
||||||
className={({ isActive }) =>
|
<NavLink
|
||||||
[styles.navItem, isActive ? styles.navItemActive : ''].filter(Boolean).join(' ')
|
key={item.path}
|
||||||
}
|
to={item.path}
|
||||||
>
|
className={({ isActive }) =>
|
||||||
<Icon size={16} className={styles.navIcon} aria-hidden="true" />
|
[styles.navItem, isActive ? styles.navItemActive : ''].filter(Boolean).join(' ')
|
||||||
{t(labelKey)}
|
}
|
||||||
</NavLink>
|
>
|
||||||
))}
|
<item.Icon size={16} className={styles.navIcon} aria-hidden="true" />
|
||||||
|
{t(item.labelKey)}
|
||||||
|
</NavLink>
|
||||||
|
),
|
||||||
|
)}
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<div className={styles.sideFooter}>
|
<div className={styles.sideFooter}>
|
||||||
|
|||||||
Reference in New Issue
Block a user