Compare commits

..

5 Commits

Author SHA1 Message Date
Shantur Rathore
6ed1e09180 fix(ui): align sidebar header icon sizes 2026-02-12 16:07:54 +00:00
Shantur Rathore
54d4cf6604 fix(ui): use PlusSquare icon export 2026-02-12 15:47:50 +00:00
Shantur Rathore
359e89971f feat(ui): add new session icon in sidebar header 2026-02-12 15:37:58 +00:00
Shantur Rathore
7f833747b0 Merge pull request #160 from NeuralNomadsAI/codenomad/issue-157
fix(ui): handle Windows paths in instance tab titles
2026-02-12 15:01:44 +00:00
Shantur Rathore
ab3f228d85 fix(ui): handle Windows paths in tab titles 2026-02-12 14:57:40 +00:00
9 changed files with 36 additions and 32 deletions

View File

@@ -11,20 +11,11 @@ interface InstanceTabProps {
onClose: () => void
}
function formatFolderName(path: string, instances: Instance[], currentInstance: Instance): string {
const name = path.split("/").pop() || path
const duplicates = instances.filter((i) => {
const iName = i.folder.split("/").pop() || i.folder
return iName === name
})
if (duplicates.length > 1) {
const index = duplicates.findIndex((i) => i.id === currentInstance.id)
return `~/${name} (${index + 1})`
}
return `~/${name}`
function getPathBasename(path: string): string {
// Instance folders can be POSIX-like (/Users/...) on macOS/Linux or Windows-like (C:\Users\...).
// Normalize by trimming trailing separators and then splitting on both '/' and '\\'.
const normalized = path.replace(/[\\/]+$/, "")
return normalized.split(/[\\/]/).pop() || path
}
const InstanceTab: Component<InstanceTabProps> = (props) => {
@@ -58,7 +49,7 @@ const InstanceTab: Component<InstanceTabProps> = (props) => {
>
<FolderOpen class="w-4 h-4 flex-shrink-0" />
<span class="tab-label">
{props.instance.folder.split("/").pop() || props.instance.folder}
{getPathBasename(props.instance.folder)}
</span>
<span
class={`status-indicator session-status ml-auto ${statusClassName()}`}

View File

@@ -4,7 +4,7 @@ import type { Session } from "../../../types/session"
import type { KeyboardShortcut } from "../../../lib/keyboard-registry"
import type { DrawerViewState } from "./types"
import { Search } from "lucide-solid"
import { PlusSquare, Search } from "lucide-solid"
import IconButton from "@suid/material/IconButton"
import MenuOpenIcon from "@suid/icons-material/MenuOpen"
import PushPinIcon from "@suid/icons-material/PushPin"
@@ -56,6 +56,20 @@ const SessionSidebar: Component<SessionSidebarProps> = (props) => (
{props.t("instanceShell.leftPanel.sessionsTitle")}
</span>
<div class="flex items-center gap-2 text-primary">
<IconButton
size="small"
color="inherit"
aria-label={props.t("sessionList.actions.newSession.ariaLabel")}
title={props.t("sessionList.actions.newSession.title")}
onClick={() => {
const result = props.onNewSession()
if (result instanceof Promise) {
void result.catch((error) => log.error("Failed to create session:", error))
}
}}
>
<PlusSquare class="w-5 h-5" />
</IconButton>
<IconButton
size="small"
color="inherit"
@@ -71,7 +85,7 @@ const SessionSidebar: Component<SessionSidebarProps> = (props) => (
},
}}
>
<Search class={props.showSearch() ? "w-4 h-4" : "w-4 h-4 opacity-70"} />
<Search class="w-5 h-5" />
</IconButton>
<IconButton
size="small"

View File

@@ -21,6 +21,8 @@ export const sessionMessages = {
"sessionList.expand.expandAriaLabel": "Expand session",
"sessionList.expand.collapseTitle": "Collapse",
"sessionList.expand.expandTitle": "Expand",
"sessionList.actions.newSession.ariaLabel": "New session",
"sessionList.actions.newSession.title": "New session",
"sessionList.actions.copyId.ariaLabel": "Copy session ID",
"sessionList.actions.copyId.title": "Copy session ID",
"sessionList.actions.rename.ariaLabel": "Rename session",

View File

@@ -21,6 +21,8 @@ export const sessionMessages = {
"sessionList.expand.expandAriaLabel": "Expandir sesión",
"sessionList.expand.collapseTitle": "Colapsar",
"sessionList.expand.expandTitle": "Expandir",
"sessionList.actions.newSession.ariaLabel": "Nueva sesión",
"sessionList.actions.newSession.title": "Nueva sesión",
"sessionList.actions.copyId.ariaLabel": "Copiar ID de sesión",
"sessionList.actions.copyId.title": "Copiar ID de sesión",
"sessionList.actions.rename.ariaLabel": "Renombrar sesión",

View File

@@ -21,6 +21,8 @@ export const sessionMessages = {
"sessionList.expand.expandAriaLabel": "Développer la session",
"sessionList.expand.collapseTitle": "Réduire",
"sessionList.expand.expandTitle": "Développer",
"sessionList.actions.newSession.ariaLabel": "Nouvelle session",
"sessionList.actions.newSession.title": "Nouvelle session",
"sessionList.actions.copyId.ariaLabel": "Copier l'ID de session",
"sessionList.actions.copyId.title": "Copier l'ID de session",
"sessionList.actions.rename.ariaLabel": "Renommer la session",

View File

@@ -21,6 +21,8 @@ export const sessionMessages = {
"sessionList.expand.expandAriaLabel": "セッションを展開",
"sessionList.expand.collapseTitle": "折りたたむ",
"sessionList.expand.expandTitle": "展開",
"sessionList.actions.newSession.ariaLabel": "新しいセッション",
"sessionList.actions.newSession.title": "新しいセッション",
"sessionList.actions.copyId.ariaLabel": "セッション ID をコピー",
"sessionList.actions.copyId.title": "セッション ID をコピー",
"sessionList.actions.rename.ariaLabel": "セッション名を変更",

View File

@@ -21,6 +21,8 @@ export const sessionMessages = {
"sessionList.expand.expandAriaLabel": "Развернуть сессию",
"sessionList.expand.collapseTitle": "Свернуть",
"sessionList.expand.expandTitle": "Развернуть",
"sessionList.actions.newSession.ariaLabel": "Новая сессия",
"sessionList.actions.newSession.title": "Новая сессия",
"sessionList.actions.copyId.ariaLabel": "Скопировать ID сессии",
"sessionList.actions.copyId.title": "Скопировать ID сессии",
"sessionList.actions.rename.ariaLabel": "Переименовать сессию",

View File

@@ -21,6 +21,8 @@ export const sessionMessages = {
"sessionList.expand.expandAriaLabel": "展开会话",
"sessionList.expand.collapseTitle": "折叠",
"sessionList.expand.expandTitle": "展开",
"sessionList.actions.newSession.ariaLabel": "新建会话",
"sessionList.actions.newSession.title": "新建会话",
"sessionList.actions.copyId.ariaLabel": "复制会话 ID",
"sessionList.actions.copyId.title": "复制会话 ID",
"sessionList.actions.rename.ariaLabel": "重命名会话",

View File

@@ -1,4 +1,4 @@
@import "github-markdown-css/github-markdown-light.css" layer(github-markdown-base);
@import "github-markdown-css/github-markdown-dark.css";
@layer components {
.markdown-body {
@@ -96,7 +96,6 @@
.markdown-body code {
font-family: var(--font-family-mono);
font-size: var(--font-size-sm);
color: var(--text-primary);
background-color: var(--surface-muted);
border: 1px solid var(--border-base);
border-radius: 4px;
@@ -109,23 +108,17 @@
background: transparent;
}
.markdown-body pre:not(.shiki) {
.markdown-body pre {
font-family: var(--font-family-mono);
font-size: var(--font-size-sm);
line-height: var(--line-height-normal);
background-color: var(--surface-code);
color: var(--text-primary);
border: 1px solid var(--border-base);
border-radius: 8px;
padding: 0.75rem;
margin: 1rem 0;
}
.markdown-body pre:not(.shiki) code,
.markdown-code-block pre:not(.shiki) code {
color: var(--text-primary);
}
.markdown-body blockquote {
border-left: 3px solid var(--border-base);
color: var(--text-secondary);
@@ -175,18 +168,12 @@
border: 1px solid var(--border-base);
padding: 0.5rem 0.75rem;
text-align: left;
color: var(--text-primary);
background-color: transparent;
}
.markdown-body th {
background-color: var(--surface-secondary);
}
.markdown-body tbody tr:nth-child(2n) {
background-color: var(--surface-muted);
}
.markdown-code-block {
position: relative;
margin: 10px 0;