Skip to content

Commit fd38f15

Browse files
committed
feat(landing): add interactive workspace preview tabs
Adds Tables, Files, Knowledge Base, Logs, and Scheduled Tasks preview components to the landing hero, with sidebar nav items that switch to each view.
1 parent 84d4128 commit fd38f15

File tree

9 files changed

+1585
-36
lines changed

9 files changed

+1585
-36
lines changed
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
import { File } from '@/components/emcn/icons'
2+
import { DocxIcon, PdfIcon } from '@/components/icons/document-icons'
3+
import type {
4+
PreviewColumn,
5+
PreviewRow,
6+
} from '@/app/(home)/components/landing-preview/components/landing-preview-resource/landing-preview-resource'
7+
import {
8+
LandingPreviewResource,
9+
ownerCell,
10+
} from '@/app/(home)/components/landing-preview/components/landing-preview-resource/landing-preview-resource'
11+
12+
/** Generic audio/zip icon using basic SVG since no dedicated component exists */
13+
function AudioIcon({ className }: { className?: string }) {
14+
return (
15+
<svg
16+
viewBox='0 0 24 24'
17+
fill='none'
18+
stroke='currentColor'
19+
strokeWidth='1.5'
20+
strokeLinecap='round'
21+
strokeLinejoin='round'
22+
className={className}
23+
>
24+
<path d='M9 18V5l12-2v13' />
25+
<circle cx='6' cy='18' r='3' />
26+
<circle cx='18' cy='16' r='3' />
27+
</svg>
28+
)
29+
}
30+
31+
function JsonlIcon({ className }: { className?: string }) {
32+
return (
33+
<svg
34+
viewBox='0 0 24 24'
35+
fill='none'
36+
stroke='currentColor'
37+
strokeWidth='1.5'
38+
strokeLinecap='round'
39+
strokeLinejoin='round'
40+
className={className}
41+
>
42+
<path d='M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z' />
43+
<path d='M14 2v4a2 2 0 0 0 2 2h4' />
44+
<path d='M10 9H8' />
45+
<path d='M16 13H8' />
46+
<path d='M16 17H8' />
47+
</svg>
48+
)
49+
}
50+
51+
function ZipIcon({ className }: { className?: string }) {
52+
return (
53+
<svg
54+
viewBox='0 0 24 24'
55+
fill='none'
56+
stroke='currentColor'
57+
strokeWidth='1.5'
58+
strokeLinecap='round'
59+
strokeLinejoin='round'
60+
className={className}
61+
>
62+
<path d='M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z' />
63+
<path d='M14 2v4a2 2 0 0 0 2 2h4' />
64+
<path d='M10 6h1' />
65+
<path d='M10 10h1' />
66+
<path d='M10 14h1' />
67+
<path d='M9 18h2v2h-2z' />
68+
</svg>
69+
)
70+
}
71+
72+
const COLUMNS: PreviewColumn[] = [
73+
{ id: 'name', header: 'Name' },
74+
{ id: 'size', header: 'Size' },
75+
{ id: 'type', header: 'Type' },
76+
{ id: 'created', header: 'Created' },
77+
{ id: 'owner', header: 'Owner' },
78+
]
79+
80+
const ROWS: PreviewRow[] = [
81+
{
82+
id: '1',
83+
cells: {
84+
name: { icon: <PdfIcon className='h-[14px] w-[14px]' />, label: 'Q1 Performance Report.pdf' },
85+
size: { label: '2.4 MB' },
86+
type: { icon: <PdfIcon className='h-[14px] w-[14px]' />, label: 'PDF' },
87+
created: { label: '3 hours ago' },
88+
owner: ownerCell('T', 'Theo L.'),
89+
},
90+
},
91+
{
92+
id: '2',
93+
cells: {
94+
name: { icon: <ZipIcon className='h-[14px] w-[14px]' />, label: 'product-screenshots.zip' },
95+
size: { label: '18.7 MB' },
96+
type: { icon: <ZipIcon className='h-[14px] w-[14px]' />, label: 'ZIP' },
97+
created: { label: '1 day ago' },
98+
owner: ownerCell('A', 'Alex M.'),
99+
},
100+
},
101+
{
102+
id: '3',
103+
cells: {
104+
name: { icon: <JsonlIcon className='h-[14px] w-[14px]' />, label: 'training-dataset.jsonl' },
105+
size: { label: '892 KB' },
106+
type: { icon: <JsonlIcon className='h-[14px] w-[14px]' />, label: 'JSONL' },
107+
created: { label: '3 days ago' },
108+
owner: ownerCell('J', 'Jordan P.'),
109+
},
110+
},
111+
{
112+
id: '4',
113+
cells: {
114+
name: { icon: <PdfIcon className='h-[14px] w-[14px]' />, label: 'brand-guidelines.pdf' },
115+
size: { label: '5.1 MB' },
116+
type: { icon: <PdfIcon className='h-[14px] w-[14px]' />, label: 'PDF' },
117+
created: { label: '1 week ago' },
118+
owner: ownerCell('S', 'Sarah K.'),
119+
},
120+
},
121+
{
122+
id: '5',
123+
cells: {
124+
name: { icon: <AudioIcon className='h-[14px] w-[14px]' />, label: 'customer-interviews.mp3' },
125+
size: { label: '45.2 MB' },
126+
type: { icon: <AudioIcon className='h-[14px] w-[14px]' />, label: 'Audio' },
127+
created: { label: 'March 20th, 2026' },
128+
owner: ownerCell('V', 'Vik M.'),
129+
},
130+
},
131+
{
132+
id: '6',
133+
cells: {
134+
name: { icon: <DocxIcon className='h-[14px] w-[14px]' />, label: 'onboarding-playbook.docx' },
135+
size: { label: '1.1 MB' },
136+
type: { icon: <DocxIcon className='h-[14px] w-[14px]' />, label: 'DOCX' },
137+
created: { label: 'March 14th, 2026' },
138+
owner: ownerCell('S', 'Sarah K.'),
139+
},
140+
},
141+
]
142+
143+
/**
144+
* Static landing preview of the Files workspace page.
145+
*/
146+
export function LandingPreviewFiles() {
147+
return (
148+
<LandingPreviewResource
149+
icon={File}
150+
title='Files'
151+
createLabel='Upload file'
152+
searchPlaceholder='Search files...'
153+
columns={COLUMNS}
154+
rows={ROWS}
155+
/>
156+
)
157+
}
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
import { Database } from '@/components/emcn/icons'
2+
import {
3+
AirtableIcon,
4+
AsanaIcon,
5+
ConfluenceIcon,
6+
GoogleDocsIcon,
7+
GoogleDriveIcon,
8+
JiraIcon,
9+
SalesforceIcon,
10+
SlackIcon,
11+
ZendeskIcon,
12+
} from '@/components/icons'
13+
import type {
14+
PreviewColumn,
15+
PreviewRow,
16+
} from '@/app/(home)/components/landing-preview/components/landing-preview-resource/landing-preview-resource'
17+
import { LandingPreviewResource } from '@/app/(home)/components/landing-preview/components/landing-preview-resource/landing-preview-resource'
18+
19+
const DB_ICON = <Database className='h-[14px] w-[14px]' />
20+
21+
function connectorIcons(icons: React.ComponentType<{ className?: string }>[]) {
22+
return {
23+
content: (
24+
<div className='flex items-center gap-1'>
25+
{icons.map((Icon, i) => (
26+
<Icon key={i} className='h-3.5 w-3.5 flex-shrink-0' />
27+
))}
28+
</div>
29+
),
30+
}
31+
}
32+
33+
const COLUMNS: PreviewColumn[] = [
34+
{ id: 'name', header: 'Name' },
35+
{ id: 'documents', header: 'Documents' },
36+
{ id: 'tokens', header: 'Tokens' },
37+
{ id: 'connectors', header: 'Connectors' },
38+
{ id: 'created', header: 'Created' },
39+
]
40+
41+
const ROWS: PreviewRow[] = [
42+
{
43+
id: '1',
44+
cells: {
45+
name: { icon: DB_ICON, label: 'Product Documentation' },
46+
documents: { label: '847' },
47+
tokens: { label: '1,284,392' },
48+
connectors: connectorIcons([AsanaIcon, GoogleDocsIcon]),
49+
created: { label: '2 days ago' },
50+
},
51+
},
52+
{
53+
id: '2',
54+
cells: {
55+
name: { icon: DB_ICON, label: 'Customer Support KB' },
56+
documents: { label: '234' },
57+
tokens: { label: '892,104' },
58+
connectors: connectorIcons([ZendeskIcon, SlackIcon]),
59+
created: { label: '1 week ago' },
60+
},
61+
},
62+
{
63+
id: '3',
64+
cells: {
65+
name: { icon: DB_ICON, label: 'Engineering Wiki' },
66+
documents: { label: '1,203' },
67+
tokens: { label: '2,847,293' },
68+
connectors: connectorIcons([ConfluenceIcon, JiraIcon]),
69+
created: { label: 'March 12th, 2026' },
70+
},
71+
},
72+
{
73+
id: '4',
74+
cells: {
75+
name: { icon: DB_ICON, label: 'Marketing Assets' },
76+
documents: { label: '189' },
77+
tokens: { label: '634,821' },
78+
connectors: connectorIcons([GoogleDriveIcon, AirtableIcon]),
79+
created: { label: 'March 5th, 2026' },
80+
},
81+
},
82+
{
83+
id: '5',
84+
cells: {
85+
name: { icon: DB_ICON, label: 'Sales Playbook' },
86+
documents: { label: '92' },
87+
tokens: { label: '418,570' },
88+
connectors: connectorIcons([SalesforceIcon]),
89+
created: { label: 'February 28th, 2026' },
90+
},
91+
},
92+
]
93+
94+
export function LandingPreviewKnowledge() {
95+
return (
96+
<LandingPreviewResource
97+
icon={Database}
98+
title='Knowledge Base'
99+
createLabel='New base'
100+
searchPlaceholder='Search knowledge bases...'
101+
columns={COLUMNS}
102+
rows={ROWS}
103+
/>
104+
)
105+
}

0 commit comments

Comments
 (0)