fix(emcn/header): icon consistency — breadcrumb menus, Connections, FolderCode (#6263)

* fix(header): give every breadcrumb menu item an icon

The resource crumb's menu (table, knowledge base, document, file) rendered
Rename/Tags/Share/Download/Delete with icons, but the folder crumb's menu
rendered bare labels. The two open from adjacent segments of the same
breadcrumb, so the inconsistency was visible side by side.

Add the matching icons to the three folder-crumb menus.

* fix(emcn): redraw Connections on the house geometry

Connections was a filled glyph in a tight 0 0 13 13 box with a 0.2
hairline stroke. At size-[14px] it rendered a 21.5px glyph at 0.22px
stroke where its neighbours render ~10.5px at 0.90px, so it read as a
different weight class in the resource registry it shares with Library,
Globe and Database.

Redraw as a stroke outline on the 24-box at 1.55, preserving the
topology: a 2x2 grid with a circle top-right, linked along the top,
down the right column, and along the bottom. Now 10.9px at 0.90px.

* fix(emcn): match FolderCode geometry to the folder family

FolderCode carried the same fill-based construction Folder did: a tight
0 0 15 13 box with a 0.3 hairline stroke. At size-[14px] it rendered a
19.9px glyph at 0.28px stroke where a standard icon renders ~10.5px at
0.90px — roughly twice the size at a third the weight.

It renders in Chat's TOOL_ICONS map for glob/mv/mkdir, directly beside
Search, File and Database, so the mismatch was visible in a single list.

Reuse Folder's body path verbatim and inset code brackets centred on the
body, so the whole folder family shares one silhouette and one weight.
This commit is contained in:
Waleed
2026-08-04 13:41:21 -07:00
committed by GitHub
parent 8ca3b27f43
commit f0e57cb73f
5 changed files with 46 additions and 36 deletions
@@ -1796,6 +1796,7 @@ export function Files() {
? [
{
label: 'Rename',
icon: Pencil,
disabled: !canEdit,
onClick: () => breadcrumbRenameRef.current.startRename(folder.id, folder.name),
},
@@ -3,7 +3,7 @@
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import type { ChipDropdownOption } from '@sim/emcn'
import { Button, ChipConfirmModal, ChipDropdown, Plus, Tooltip, toast } from '@sim/emcn'
import { Database, FolderPlus } from '@sim/emcn/icons'
import { Database, FolderPlus, Pencil, Trash } from '@sim/emcn/icons'
import { createLogger } from '@sim/logger'
import { getErrorMessage } from '@sim/utils/errors'
import { useParams, useRouter } from 'next/navigation'
@@ -925,6 +925,7 @@ export function Knowledge() {
? [
{
label: 'Rename',
icon: Pencil,
onClick: () => {
const folder = breadcrumbs[breadcrumbs.length - 1]
breadcrumbRenameRef.current.startRename(folder.id, folder.name)
@@ -932,6 +933,7 @@ export function Knowledge() {
},
{
label: 'Delete',
icon: Trash,
onClick: () => setFolderPendingDelete(breadcrumbs[breadcrumbs.length - 1]),
},
]
@@ -3,7 +3,7 @@
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import type { ComboboxOption } from '@sim/emcn'
import { ChipCombobox, ChipConfirmModal, Plus, toast, Upload } from '@sim/emcn'
import { Columns3, FolderPlus, Rows3, Table as TableIcon } from '@sim/emcn/icons'
import { Columns3, FolderPlus, Pencil, Rows3, Table as TableIcon, Trash } from '@sim/emcn/icons'
import { createLogger } from '@sim/logger'
import { getErrorMessage } from '@sim/utils/errors'
import { generateId } from '@sim/utils/id'
@@ -467,11 +467,13 @@ export function Tables() {
return [
{
label: 'Rename',
icon: Pencil,
disabled: !canEdit,
onClick: () => breadcrumbRename.startRename(folder.id, folder.name),
},
{
label: 'Delete',
icon: Trash,
disabled: !canEdit,
/**
* The only way to delete the folder you are inside — its own row is not in the list.
+22 -10
View File
@@ -1,26 +1,38 @@
import type { SVGProps } from 'react'
/**
* Connections icon component
* Connections icon component - a four-node lattice for integrations
*
* Redrawn on the house geometry (24-box, 1.55 stroke, round joins) so it sits
* at the weight of the icons it shares the resource registry with. The original
* topology is preserved: a 2x2 grid with a circle top-right, linked left-to-
* right along the top, down the right column, and left-to-right along the
* bottom.
*
* @param props - SVG properties including className, fill, etc.
*/
export function Connections(props: SVGProps<SVGSVGElement>) {
return (
<svg
width='13'
height='13'
viewBox='0 0 13 13'
width='24'
height='24'
viewBox='-1 -2 24 24'
fill='none'
stroke='currentColor'
strokeWidth='1.55'
strokeLinecap='round'
strokeLinejoin='round'
xmlns='http://www.w3.org/2000/svg'
aria-hidden='true'
{...props}
>
<path
d='M10.167 0C11.73 0 13 1.27 13 2.83C13 4.23 11.993 5.38 10.667 5.62V7.34C10.99 7.34 11.27 7.35 11.51 7.38C11.89 7.43 12.23 7.54 12.51 7.82C12.79 8.1 12.9 8.45 12.95 8.82C13 9.18 13 9.63 13 10.167C13 10.7 13 11.155 12.95 11.51C12.9 11.89 12.79 12.23 12.51 12.51C12.23 12.79 11.89 12.9 11.51 12.95C11.155 13 10.7 13 10.167 13C9.63 13 9.18 13 8.82 12.95C8.45 12.9 8.1 12.79 7.82 12.51C7.54 12.23 7.43 11.89 7.38 11.51C7.35 11.27 7.34 10.99 7.34 10.667H5.66C5.66 10.99 5.65 11.27 5.62 11.51C5.57 11.89 5.46 12.23 5.18 12.51C4.9 12.79 4.55 12.9 4.18 12.95C3.82 13 3.37 13 2.83 13C2.3 13 1.85 13 1.49 12.95C1.11 12.9 0.77 12.79 0.49 12.51C0.21 12.23 0.1 11.89 0.05 11.51C0 11.155 -5.3e-07 10.7 0 10.167C0 9.63 0 9.18 0.05 8.82C0.1 8.45 0.21 8.1 0.49 7.82C0.77 7.54 1.11 7.43 1.49 7.38C1.85 7.33 2.3 7.33 2.83 7.33C3.37 7.33 3.82 7.33 4.18 7.38C4.55 7.43 4.9 7.54 5.18 7.82C5.46 8.1 5.57 8.45 5.62 8.82C5.65 9.06 5.66 9.34 5.66 9.67H7.34C7.34 9.34 7.35 9.06 7.38 8.82C7.43 8.45 7.54 8.1 7.82 7.82C8.1 7.54 8.45 7.43 8.82 7.38C9.06 7.35 9.34 7.34 9.67 7.34V5.62C8.5 5.41 7.59 4.5 7.38 3.33H5.66C5.66 3.66 5.65 3.94 5.62 4.18C5.57 4.55 5.46 4.9 5.18 5.18C4.9 5.46 4.55 5.57 4.18 5.62C3.82 5.67 3.37 5.67 2.83 5.67C2.3 5.67 1.85 5.67 1.49 5.62C1.11 5.57 0.77 5.46 0.49 5.18C0.21 4.9 0.1 4.55 0.05 4.18C0 3.82 0 3.37 0 2.83C-5.67e-07 2.3 0 1.85 0.05 1.49C0.1 1.11 0.21 0.77 0.49 0.49C0.77 0.21 1.11 0.1 1.49 0.05C1.85 0 2.3 -5.67e-07 2.83 0C3.37 0 3.82 0 4.18 0.05C4.55 0.1 4.9 0.21 5.18 0.49C5.46 0.77 5.57 1.11 5.62 1.49C5.65 1.73 5.66 2.01 5.66 2.33H7.38C7.62 1.01 8.77 0 10.167 0ZM2.83 8.33C2.27 8.33 1.9 8.33 1.62 8.37C1.36 8.41 1.26 8.47 1.2 8.53C1.13 8.59 1.07 8.69 1.04 8.95C1 9.23 1 9.6 1 10.167C1 10.73 1 11.1 1.04 11.38C1.07 11.64 1.13 11.74 1.2 11.8C1.26 11.87 1.36 11.93 1.62 11.96C1.9 12 2.27 12 2.83 12C3.4 12 3.77 12 4.05 11.96C4.31 11.93 4.41 11.87 4.47 11.8C4.53 11.74 4.59 11.64 4.63 11.38C4.67 11.1 4.67 10.73 4.67 10.167C4.67 9.6 4.67 9.23 4.63 8.95C4.59 8.69 4.53 8.59 4.47 8.53C4.41 8.47 4.31 8.41 4.05 8.37C3.77 8.33 3.4 8.33 2.83 8.33ZM10.167 8.33C9.6 8.33 9.23 8.33 8.95 8.37C8.69 8.41 8.59 8.47 8.53 8.53C8.47 8.59 8.41 8.69 8.37 8.95C8.33 9.23 8.33 9.6 8.33 10.167C8.33 10.73 8.33 11.1 8.37 11.38C8.41 11.64 8.47 11.74 8.53 11.8C8.59 11.87 8.69 11.93 8.95 11.96C9.23 12 9.6 12 10.167 12C10.73 12 11.1 12 11.38 11.96C11.64 11.93 11.74 11.87 11.8 11.8C11.87 11.74 11.93 11.64 11.96 11.38C12 11.1 12 10.73 12 10.167C12 9.6 12 9.23 11.96 8.95C11.93 8.69 11.87 8.59 11.8 8.53C11.74 8.47 11.64 8.41 11.38 8.37C11.1 8.33 10.73 8.33 10.167 8.33ZM2.83 1C2.27 1 1.9 1 1.62 1.04C1.36 1.07 1.26 1.13 1.2 1.2C1.13 1.26 1.07 1.36 1.04 1.62C1 1.9 1 2.27 1 2.83C1 3.4 1 3.77 1.04 4.05C1.07 4.31 1.13 4.41 1.2 4.47C1.26 4.53 1.36 4.59 1.62 4.63C1.9 4.67 2.27 4.67 2.83 4.67C3.4 4.67 3.77 4.67 4.05 4.63C4.31 4.59 4.41 4.53 4.47 4.47C4.53 4.41 4.59 4.31 4.63 4.05C4.67 3.77 4.67 3.4 4.67 2.83C4.67 2.27 4.67 1.9 4.63 1.62C4.59 1.36 4.53 1.26 4.47 1.2C4.41 1.13 4.31 1.07 4.05 1.04C3.77 1 3.4 1 2.83 1ZM10.167 1C9.15 1 8.33 1.82 8.33 2.83C8.33 3.85 9.15 4.67 10.167 4.67C11.18 4.67 12 3.85 12 2.83C12 1.82 11.18 1 10.167 1Z'
fill='currentColor'
stroke='currentColor'
strokeWidth='0.2'
/>
<path d='M4.25 1.25H6.25A2 2 0 0 1 8.25 3.25V5.25A2 2 0 0 1 6.25 7.25H4.25A2 2 0 0 1 2.25 5.25V3.25A2 2 0 0 1 4.25 1.25Z' />
<path d='M15.25 1.75A2.5 2.5 0 1 1 15.25 6.75A2.5 2.5 0 1 1 15.25 1.75Z' />
<path d='M4.25 12.75H6.25A2 2 0 0 1 8.25 14.75V16.75A2 2 0 0 1 6.25 18.75H4.25A2 2 0 0 1 2.25 16.75V14.75A2 2 0 0 1 4.25 12.75Z' />
<path d='M14.25 12.75H16.25A2 2 0 0 1 18.25 14.75V16.75A2 2 0 0 1 16.25 18.75H14.25A2 2 0 0 1 12.25 16.75V14.75A2 2 0 0 1 14.25 12.75Z' />
<path d='M8.25 4.25H12.75' />
<path d='M15.25 6.75V12.75' />
<path d='M8.25 15.75H12.25' />
</svg>
)
}
+17 -24
View File
@@ -1,40 +1,33 @@
import type { SVGProps } from 'react'
/**
* FolderCode icon component
* FolderCode icon component - a {@link Folder} carrying code brackets
*
* Shares {@link Folder}'s body path verbatim so the folder family reads as one
* silhouette at one weight. The brackets are centred on the body (x 9.125,
* y 11.25) rather than on the viewBox, so they sit inside the folder rather
* than drifting toward the flap.
*
* @param props - SVG properties including className, fill, etc.
*/
export function FolderCode(props: SVGProps<SVGSVGElement>) {
return (
<svg
width='15'
height='13'
viewBox='0 0 15 13'
width='24'
height='24'
viewBox='-1 -2 24 24'
fill='none'
stroke='currentColor'
strokeWidth='1.55'
strokeLinecap='round'
strokeLinejoin='round'
xmlns='http://www.w3.org/2000/svg'
aria-hidden='true'
{...props}
>
<path
d='M4.32e-07 5.83V3.8C4.32e-07 3.2 0 2.72 0.03 2.33C0.07 1.94 0.14 1.6 0.32 1.28C0.54 0.88 0.88 0.54 1.28 0.32C1.6 0.14 1.94 0.07 2.33 0.03C2.72 0 3.2 5.96e-05 3.8 5.96e-05C4.53 5.93e-05 5.03 -0.01 5.48 0.16C6.47 0.53 6.87 1.45 7.19 2.1L7.48 2.67H10.33C11.025 2.67 11.58 2.67 12.03 2.71C12.48 2.76 12.874 2.86 13.222 3.09C13.495 3.27 13.73 3.51 13.91 3.78C14.14 4.13 14.24 4.52 14.29 4.97C14.33 5.42 14.33 5.98 14.33 6.67C14.33 7.83 14.33 8.73 14.26 9.46C14.19 10.19 14.03 10.78 13.69 11.3C13.41 11.71 13.05 12.07 12.63 12.35C12.11 12.7 11.52 12.85 10.79 12.93C10.07 13 9.16 13 8 13H7.17C5.61 13 4.39 13 3.44 12.87C2.48 12.74 1.72 12.47 1.12 11.877C0.53 11.28 0.26 10.52 0.13 9.56C0 8.61 4.32e-07 7.39 4.32e-07 5.83ZM1 5.83C1 7.42 1 8.56 1.12 9.42C1.23 10.28 1.45 10.79 1.83 11.17C2.21 11.55 2.72 11.77 3.58 11.88C4.44 12 5.58 12 7.17 12H8C9.18 12 10.029 12 10.69 11.93C11.34 11.87 11.75 11.74 12.07 11.52C12.38 11.32 12.65 11.05 12.86 10.74C13.07 10.42 13.2 10.01 13.27 9.35C13.33 8.7 13.33 7.85 13.33 6.67C13.33 5.95 13.33 5.46 13.29 5.07C13.26 4.7 13.19 4.49 13.08 4.33C12.97 4.17 12.83 4.03 12.67 3.92C12.51 3.81 12.3 3.74 11.93 3.71C11.54 3.67 11.046 3.67 10.33 3.67H5.17C4.89 3.67 4.67 3.44 4.67 3.17C4.67 2.89 4.89 2.67 5.17 2.67H6.36L6.3 2.55C5.92 1.8 5.68 1.3 5.12 1.1C4.89 1.01 4.61 1 3.8 1C3.18 1 2.75 1 2.42 1.03C2.1 1.06 1.91 1.11 1.77 1.19C1.53 1.33 1.33 1.53 1.19 1.77C1.11 1.91 1.06 2.1 1.03 2.42C1 2.75 1 3.18 1 3.8V5.83Z'
fill='currentColor'
stroke='currentColor'
strokeWidth='0.3'
/>
<g transform='translate(0, 0.3)'>
<path
d='M9.83 6.12C9.617 5.94 9.3 5.96 9.12 6.17C8.94 6.38 8.96 6.7 9.17 6.88L9.79 7.41C9.83 7.44 9.86 7.47 9.89 7.5C9.86 7.53 9.83 7.56 9.79 7.59L9.17 8.12C8.96 8.3 8.94 8.62 9.12 8.83C9.3 9.04 9.617 9.06 9.83 8.88L10.44 8.35C10.56 8.25 10.69 8.14 10.778 8.04C10.86 7.94 10.97 7.79 10.99 7.59L11 7.5L10.99 7.41C10.97 7.21 10.86 7.06 10.778 6.96C10.69 6.86 10.56 6.75 10.44 6.65L9.83 6.12Z'
fill='currentColor'
/>
<path
d='M4.51 6.12C4.72 5.94 5.03 5.96 5.21 6.17C5.39 6.38 5.37 6.7 5.16 6.88L4.55 7.41C4.51 7.44 4.47 7.47 4.44 7.5C4.47 7.53 4.51 7.56 4.55 7.59L5.16 8.12C5.37 8.3 5.39 8.62 5.21 8.83C5.03 9.04 4.72 9.06 4.51 8.88L3.89 8.35C3.78 8.25 3.65 8.14 3.56 8.04C3.469 7.94 3.36 7.79 3.34 7.59L3.33 7.5L3.34 7.41C3.36 7.21 3.469 7.06 3.56 6.96C3.65 6.86 3.78 6.75 3.89 6.65L4.51 6.12Z'
fill='currentColor'
/>
<path
d='M7.37 5.65C7.47 5.39 7.76 5.27 8.02 5.37C8.28 5.47 8.4 5.76 8.3 6.02L6.96 9.35C6.86 9.61 6.57 9.73 6.31 9.63C6.06 9.53 5.93 9.24 6.04 8.98L7.37 5.65Z'
fill='currentColor'
/>
</g>
<path d='M3.75 17.25A2 2 0 0 1 1.75 15.25V4.25A2 2 0 0 1 3.75 2.25H7L9.5 5.25H14.5A2 2 0 0 1 16.5 7.25V15.25A2 2 0 0 1 14.5 17.25Z' />
<path d='M7.75 9.5L6 11.25L7.75 13' />
<path d='M10.5 9.5L12.25 11.25L10.5 13' />
</svg>
)
}