Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
d51a7cc
feat(resources): empty-state graphics for knowledge, tables, logs, fi…
andresdjasso Aug 18, 2026
4e0f3de
improvement(tables): redraw the empty-state graphic in the house gray…
andresdjasso Aug 18, 2026
7f1e4ab
improvement(tables): strip the empty-state graphic to ruled lines and…
andresdjasso Aug 18, 2026
ff7d91e
improvement(tables): make the selected cell opaque and a shade darker
andresdjasso Aug 18, 2026
444e26d
improvement(tables): round the empty-state grid's crisp corner
andresdjasso Aug 18, 2026
7e3cc9a
feat(knowledge,tables): redraw knowledge's empty state and add docs/c…
andresdjasso Aug 18, 2026
28968dc
review(knowledge): three candidate depictions, and lead with the crea…
andresdjasso Aug 18, 2026
94f28b2
feat(knowledge): draw the empty state as an isometric set of volumes
andresdjasso Aug 18, 2026
96068b8
improvement(knowledge): brand the front volume instead of laying a pa…
andresdjasso Aug 18, 2026
65bad8c
improvement(knowledge): bore through the front volume, and fade the s…
andresdjasso Aug 18, 2026
90a28a3
feat(resources): logs and files graphics, and settle the set as one c…
andresdjasso Aug 18, 2026
a2e27ca
revert(skills): drop the skills empty state
andresdjasso Aug 18, 2026
4851806
cleanup(resources): fix empty-state flashes and share the iso ramp
waleedlatif1 Aug 19, 2026
69caeab
simplify(resources): reuse the iso recipe and let the frame own its l…
waleedlatif1 Aug 19, 2026
c3ab60b
simplify(resources): decide list emptiness in one place
waleedlatif1 Aug 19, 2026
63c6360
chore(audits): re-record the page module-graph baseline
waleedlatif1 Aug 19, 2026
123fb85
fix(resources): hold the empty state until folders resolve
waleedlatif1 Aug 19, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
ISO_FILL_LOW,
ISO_FILL_MID,
ISO_STROKE,
} from '@/app/(landing)/components/mothership/components/iso-marks/iso-illustration-style'
} from '@/components/iso/iso-illustration-style'

export interface IsoBuildIllustrationProps {
size?: number
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
ISO_FILL_PULSE_LOW,
ISO_FILL_PULSE_MID,
ISO_STROKE,
} from '@/app/(landing)/components/mothership/components/iso-marks/iso-illustration-style'
} from '@/components/iso/iso-illustration-style'

export interface IsoIngestIllustrationProps {
size?: number
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
ISO_FILL_LOW,
ISO_FILL_MID,
ISO_STROKE,
} from '@/app/(landing)/components/mothership/components/iso-marks/iso-illustration-style'
} from '@/components/iso/iso-illustration-style'

export interface IsoIntegrateIllustrationProps {
size?: number
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
ISO_FILL_LOW,
ISO_FILL_MID,
ISO_STROKE,
} from '@/app/(landing)/components/mothership/components/iso-marks/iso-illustration-style'
} from '@/components/iso/iso-illustration-style'

export interface IsoMonitorIllustrationProps {
size?: number
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { ChipLink } from '@sim/emcn'
import { BookOpen } from '@sim/emcn/icons'

interface EmptyStateDocsLinkProps {
href: string
}

/** The docs chip every resource empty state carries, so the four stay identical. */
export function EmptyStateDocsLink({ href }: EmptyStateDocsLinkProps) {
return (
<ChipLink
href={href}
target='_blank'
rel='noopener noreferrer'
variant='border'
leftIcon={BookOpen}
>
Docs
</ChipLink>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import { Chip, cn } from '@sim/emcn'
import { Upload } from '@sim/emcn/icons'
import { EmptyState } from '@/components/empty-state/empty-state'
import { EmptyStateDocsLink } from '@/app/workspace/[workspaceId]/components/resource/components/resource-empty-state/docs-link'

const FILES_DOCS_URL = 'https://docs.sim.ai/files'

/**
* Hairline contours, matching the tables grid's 1px `--border-1` rules and the
* knowledge mark's thinned strokes — the graphics sit one nav item apart, so a
* heavier outline here would read as a different illustration system.
*
* Fills stay near the top of the surface ramp for the same reason: the border
* draws the folder and the fill only has to separate one layer from the next. A
* solid mid-grey body made this the heaviest thing on the page.
*/
const HAIRLINE = {
stroke: 'var(--border-1)',
strokeWidth: 1.1,
strokeLinejoin: 'round' as const,
} as const

const FOLDER_BACK = [
'M 22 34',
'H 66',
'Q 72 34 75.5 38',
'L 82.5 46',
'Q 86 50 92 50',
'H 178',
'Q 188 50 188 60',
'V 140',
'Q 188 150 178 150',
'H 22',
'Q 12 150 12 140',
'V 44',
'Q 12 34 22 34',
'Z',
].join(' ')

/**
* Dissolves upward, so the folder rises out of the page while its front panel
* stays crisp where the copy begins. Running it the other way — the direction the
* logs feed fades — ate the panel's base and left the tab hanging.
*/
const FOLDER_FADE =
'[-webkit-mask-image:linear-gradient(to_top,#000_58%,transparent_100%)] [mask-image:linear-gradient(to_top,#000_58%,transparent_100%)]'

/**
* A folder held open with sheets standing proud of its front panel.
*
* Depth is carried by the surface ramp rather than by shadow: the back panel is the
* darkest tier, the sheets the lightest, the front panel between them. Shadows
* would need separate light and dark recipes; the ramp inverts on its own.
*
* Every outer corner shares the same 10-unit radius so the silhouette reads as a
* single drawn shape — mixing radii makes the corners fight each other at this size.
*/
function FilesGraphic() {
return (
<svg
viewBox='0 0 200 160'
width={185}
height={148}
fill='none'
aria-hidden='true'
focusable='false'
className={cn('block max-w-none shrink-0', FOLDER_FADE)}
>
<path d={FOLDER_BACK} fill='var(--surface-4)' {...HAIRLINE} />

<rect x='34' y='56' width='132' height='84' rx='5' fill='var(--surface-2)' {...HAIRLINE} />
<rect x='26' y='64' width='148' height='76' rx='5' fill='var(--surface-2)' {...HAIRLINE} />

<rect x='12' y='74' width='176' height='76' rx='10' fill='var(--surface-2)' {...HAIRLINE} />
</svg>
)
}

interface FilesEmptyStateProps {
/** Opens the file picker — the same action the header's upload chip runs. */
onUpload: () => void
/** Mirrors the header chip's disabled state: no edit rights, or an upload in flight. */
uploadDisabled?: boolean
}

/** Empty state for the files list when the workspace has none. */
export function FilesEmptyState({ onUpload, uploadDisabled = false }: FilesEmptyStateProps) {
return (
<EmptyState
graphic={<FilesGraphic />}
title='Files'
description='Upload files to share them across your team and every agent.'
action={
<>
<Chip variant='primary' onClick={onUpload} disabled={uploadDisabled} leftIcon={Upload}>
Upload
</Chip>
<EmptyStateDocsLink href={FILES_DOCS_URL} />
</>
}
/>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export { FilesEmptyState } from '@/app/workspace/[workspaceId]/components/resource/components/resource-empty-state/files-empty-state'
export { KnowledgeEmptyState } from '@/app/workspace/[workspaceId]/components/resource/components/resource-empty-state/knowledge-empty-state'
export { LogsEmptyState } from '@/app/workspace/[workspaceId]/components/resource/components/resource-empty-state/logs-empty-state'
export { TablesEmptyState } from '@/app/workspace/[workspaceId]/components/resource/components/resource-empty-state/tables-empty-state'
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { Chip } from '@sim/emcn'
import { Plus } from '@sim/emcn/icons'
import { EmptyState } from '@/components/empty-state/empty-state'
import { EmptyStateDocsLink } from '@/app/workspace/[workspaceId]/components/resource/components/resource-empty-state/docs-link'
import { KnowledgeIsoMark } from '@/app/workspace/[workspaceId]/components/resource/components/resource-empty-state/knowledge-iso'

const KNOWLEDGE_DOCS_URL = 'https://docs.sim.ai/knowledgebase'

interface KnowledgeEmptyStateProps {
/** Opens the create-base modal — the same action the header's primary chip runs. */
onCreate: () => void
/** Mirrors the header chip's disabled state: no edit rights on the workspace. */
createDisabled?: boolean
}

/** Empty state for the knowledge bases list when the workspace has none. */
export function KnowledgeEmptyState({
onCreate,
createDisabled = false,
}: KnowledgeEmptyStateProps) {
return (
<EmptyState
graphic={<KnowledgeIsoMark />}
title='Knowledge bases'
description='Upload documents to give your agents a memory they can search.'
action={
<>
<Chip variant='primary' onClick={onCreate} disabled={createDisabled} leftIcon={Plus}>
New base
</Chip>
<EmptyStateDocsLink href={KNOWLEDGE_DOCS_URL} />
</>
}
/>
)
}
Loading
Loading