Skip to content

Commit c1d788c

Browse files
improvement(integrations, models): ui/ux (#4105)
* improvement(integrations, models): ui/ux * fix(models, integrations): dedup ChevronArrow/provider colors, fix UTC date rendering - Extract PROVIDER_COLORS and getProviderColor to model-colors.ts to eliminate identical definitions in model-comparison-charts and model-timeline-chart - Remove duplicate private ChevronArrow from integration-card; import the exported one from model-primitives instead - Add timeZone: 'UTC' to formatShortDate so ISO date-only strings (parsed as UTC midnight) render the correct calendar day in all timezones * refactor(models): rename model-colors.ts to consts.ts * improvement(models): derive provider colors/resellers from definitions, reorient FAQs to agent builder Dynamic data: - Add `color` and `isReseller` fields to ProviderDefinition interface - Move brand colors for all 10 providers into their definitions - Mark 6 reseller providers (Azure, Bedrock, Vertex, OpenRouter, Fireworks) - consts.ts now derives color map from MODEL_CATALOG_PROVIDERS - model-comparison-charts derives RESELLER_PROVIDERS from catalog - Fix deepseek name: Deepseek → DeepSeek; remove now-redundant PROVIDER_NAME_OVERRIDES and getProviderDisplayName from utils - Add color/isReseller fields to CatalogProvider; clean up duplicate providerDisplayName in searchText array FAQs: - Replace all 4 main-page FAQs with 5 agent-builder-oriented ones covering model selection, context windows, pricing, tool use, and how to use models in a Sim agent workflow - buildProviderFaqs: add conditional tool use FAQ per provider - buildModelFaqs: add bestFor FAQ (conditional on field presence); improve context window answer to explain agent implications; tighten capabilities answer wording * chore(models): remove model-colors.ts (superseded by consts.ts) * update footer --------- Co-authored-by: waleed <walif6@gmail.com>
1 parent bad78cc commit c1d788c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+2382
-1550
lines changed

apps/sim/app/(landing)/blog/[slug]/page.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ export default async function Page({ params }: { params: Promise<{ slug: string
161161
<h3 className='font-[430] font-season text-lg text-white leading-tight tracking-[-0.01em]'>
162162
{p.title}
163163
</h3>
164-
<p className='line-clamp-2 text-[#F6F6F0]/50 text-sm leading-[150%]'>
164+
<p className='line-clamp-2 text-[var(--landing-text-muted)] text-sm leading-[150%]'>
165165
{p.description}
166166
</p>
167167
</div>

apps/sim/app/(landing)/blog/page.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ export default async function BlogIndex({
110110
<h1 className='text-balance font-[430] font-season text-[28px] text-white leading-[100%] tracking-[-0.02em] lg:text-[40px]'>
111111
Latest from Sim
112112
</h1>
113-
<p className='max-w-[360px] font-[430] font-season text-[#F6F6F0]/50 text-sm leading-[150%] tracking-[0.02em] lg:text-base'>
113+
<p className='max-w-[540px] font-[430] font-season text-[var(--landing-text-muted)] text-sm leading-[150%] tracking-[0.02em] lg:text-base'>
114114
Announcements, insights, and guides for building AI agent workflows.
115115
</p>
116116
</div>
@@ -152,7 +152,7 @@ export default async function BlogIndex({
152152
<h3 className='font-[430] font-season text-lg text-white leading-tight tracking-[-0.01em]'>
153153
{p.title}
154154
</h3>
155-
<p className='line-clamp-2 text-[#F6F6F0]/50 text-sm leading-[150%]'>
155+
<p className='line-clamp-2 text-[var(--landing-text-muted)] text-sm leading-[150%]'>
156156
{p.description}
157157
</p>
158158
</div>
@@ -191,7 +191,7 @@ export default async function BlogIndex({
191191
<h3 className='font-[430] font-season text-base text-white leading-tight tracking-[-0.01em] lg:text-lg'>
192192
{p.title}
193193
</h3>
194-
<p className='line-clamp-2 text-[#F6F6F0]/40 text-sm leading-[150%]'>
194+
<p className='line-clamp-2 text-[var(--landing-text-muted)] text-sm leading-[150%]'>
195195
{p.description}
196196
</p>
197197
</div>

apps/sim/app/(landing)/components/footer/footer.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,8 @@ const INTEGRATION_LINKS: FooterItem[] = [
6363
{ label: 'Linear', href: 'https://docs.sim.ai/tools/linear', external: true },
6464
{ label: 'Airtable', href: 'https://docs.sim.ai/tools/airtable', external: true },
6565
{ label: 'Firecrawl', href: 'https://docs.sim.ai/tools/firecrawl', external: true },
66-
{ label: 'Pinecone', href: 'https://docs.sim.ai/tools/pinecone', external: true },
6766
{ label: 'Discord', href: 'https://docs.sim.ai/tools/discord', external: true },
6867
{ label: 'Microsoft Teams', href: 'https://docs.sim.ai/tools/microsoft_teams', external: true },
69-
{ label: 'Outlook', href: 'https://docs.sim.ai/tools/outlook', external: true },
7068
{ label: 'Telegram', href: 'https://docs.sim.ai/tools/telegram', external: true },
7169
]
7270

apps/sim/app/(landing)/components/landing-faq.tsx

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
'use client'
22

33
import { useState } from 'react'
4+
import { AnimatePresence, motion } from 'framer-motion'
45
import { ChevronDown } from '@/components/emcn'
56
import { cn } from '@/lib/core/utils/cn'
67

@@ -15,46 +16,67 @@ interface LandingFAQProps {
1516

1617
export function LandingFAQ({ faqs }: LandingFAQProps) {
1718
const [openIndex, setOpenIndex] = useState<number | null>(0)
19+
const [hoveredIndex, setHoveredIndex] = useState<number | null>(null)
1820

1921
return (
20-
<div className='divide-y divide-[var(--landing-border)]'>
22+
<div>
2123
{faqs.map(({ question, answer }, index) => {
2224
const isOpen = openIndex === index
25+
const isHovered = hoveredIndex === index
26+
const showDivider = index > 0 && hoveredIndex !== index && hoveredIndex !== index - 1
2327

2428
return (
2529
<div key={question}>
30+
<div
31+
className={cn(
32+
'h-px w-full bg-[var(--landing-bg-elevated)]',
33+
index === 0 || !showDivider ? 'invisible' : 'visible'
34+
)}
35+
/>
2636
<button
2737
type='button'
2838
onClick={() => setOpenIndex(isOpen ? null : index)}
29-
className='flex w-full items-start justify-between gap-4 py-5 text-left'
39+
onMouseEnter={() => setHoveredIndex(index)}
40+
onMouseLeave={() => setHoveredIndex(null)}
41+
className='-mx-6 flex w-[calc(100%+3rem)] items-center justify-between gap-4 px-6 py-4 text-left transition-colors hover:bg-[var(--landing-bg-elevated)]'
3042
aria-expanded={isOpen}
3143
>
3244
<span
3345
className={cn(
34-
'font-[500] text-[15px] leading-snug transition-colors',
46+
'text-[15px] leading-snug tracking-[-0.02em] transition-colors',
3547
isOpen
3648
? 'text-[var(--landing-text)]'
37-
: 'text-[var(--landing-text-muted)] hover:text-[var(--landing-text)]'
49+
: 'text-[var(--landing-text-body)] hover:text-[var(--landing-text)]'
3850
)}
3951
>
4052
{question}
4153
</span>
4254
<ChevronDown
4355
className={cn(
44-
'mt-0.5 h-4 w-4 shrink-0 text-[#555] transition-transform duration-200',
56+
'h-3 w-3 shrink-0 text-[var(--landing-text-subtle)] transition-transform duration-200',
4557
isOpen ? 'rotate-180' : 'rotate-0'
4658
)}
4759
aria-hidden='true'
4860
/>
4961
</button>
5062

51-
{isOpen && (
52-
<div className='pb-5'>
53-
<p className='text-[14px] text-[var(--landing-text-muted)] leading-[1.75]'>
54-
{answer}
55-
</p>
56-
</div>
57-
)}
63+
<AnimatePresence initial={false}>
64+
{isOpen && (
65+
<motion.div
66+
initial={{ height: 0, opacity: 0 }}
67+
animate={{ height: 'auto', opacity: 1 }}
68+
exit={{ height: 0, opacity: 0 }}
69+
transition={{ duration: 0.25, ease: [0.4, 0, 0.2, 1] }}
70+
className='overflow-hidden'
71+
>
72+
<div className='pt-2 pb-4'>
73+
<p className='text-[14px] text-[var(--landing-text-body)] leading-[1.75]'>
74+
{answer}
75+
</p>
76+
</div>
77+
</motion.div>
78+
)}
79+
</AnimatePresence>
5880
</div>
5981
)
6082
})}
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
import type { ComponentType, SVGProps } from 'react'
2+
import Link from 'next/link'
3+
import {
4+
AgentIcon,
5+
ApiIcon,
6+
McpIcon,
7+
PackageSearchIcon,
8+
TableIcon,
9+
WorkflowIcon,
10+
} from '@/components/icons'
11+
12+
interface ProductLink {
13+
label: string
14+
description: string
15+
href: string
16+
external?: boolean
17+
icon: ComponentType<SVGProps<SVGSVGElement>>
18+
}
19+
20+
interface SidebarLink {
21+
label: string
22+
href: string
23+
external?: boolean
24+
}
25+
26+
const PLATFORM: ProductLink[] = [
27+
{
28+
label: 'Workflows',
29+
description: 'Visual AI automation builder',
30+
href: 'https://docs.sim.ai/getting-started',
31+
external: true,
32+
icon: WorkflowIcon,
33+
},
34+
{
35+
label: 'Agent',
36+
description: 'Build autonomous AI agents',
37+
href: 'https://docs.sim.ai/blocks/agent',
38+
external: true,
39+
icon: AgentIcon,
40+
},
41+
{
42+
label: 'MCP',
43+
description: 'Connect external tools',
44+
href: 'https://docs.sim.ai/mcp',
45+
external: true,
46+
icon: McpIcon,
47+
},
48+
{
49+
label: 'Knowledge Base',
50+
description: 'Retrieval-augmented context',
51+
href: 'https://docs.sim.ai/knowledgebase',
52+
external: true,
53+
icon: PackageSearchIcon,
54+
},
55+
{
56+
label: 'Tables',
57+
description: 'Structured data storage',
58+
href: 'https://docs.sim.ai/tables',
59+
external: true,
60+
icon: TableIcon,
61+
},
62+
{
63+
label: 'API',
64+
description: 'Deploy workflows as endpoints',
65+
href: 'https://docs.sim.ai/api-reference/getting-started',
66+
external: true,
67+
icon: ApiIcon,
68+
},
69+
]
70+
71+
const EXPLORE: SidebarLink[] = [
72+
{ label: 'Models', href: '/models' },
73+
{ label: 'Integrations', href: '/integrations' },
74+
{ label: 'Changelog', href: '/changelog' },
75+
{ label: 'Self-hosting', href: 'https://docs.sim.ai/self-hosting', external: true },
76+
]
77+
78+
function DropdownLink({ link }: { link: ProductLink }) {
79+
const Icon = link.icon
80+
const Tag = link.external ? 'a' : Link
81+
const props = link.external
82+
? { href: link.href, target: '_blank' as const, rel: 'noopener noreferrer' }
83+
: { href: link.href }
84+
85+
return (
86+
<Tag
87+
{...props}
88+
className='group/item flex items-start gap-2.5 rounded-[5px] px-2.5 py-2 transition-colors hover:bg-[var(--landing-bg-elevated)]'
89+
>
90+
<Icon className='mt-0.5 h-[15px] w-[15px] shrink-0 text-[var(--landing-text-icon)]' />
91+
<div className='flex flex-col'>
92+
<span className='font-[430] font-season text-[13px] text-white leading-tight'>
93+
{link.label}
94+
</span>
95+
<span className='font-season text-[12px] text-[var(--landing-text-subtle)] leading-[150%]'>
96+
{link.description}
97+
</span>
98+
</div>
99+
</Tag>
100+
)
101+
}
102+
103+
export function ProductDropdown() {
104+
return (
105+
<div className='flex w-[560px] rounded-[5px] border border-[var(--landing-bg-elevated)] bg-[var(--landing-bg)] shadow-overlay'>
106+
<div className='flex-1 p-2'>
107+
<div className='mb-1 px-2.5 pt-1'>
108+
<span className='font-[430] font-season text-[11px] text-[var(--landing-text-subtle)] uppercase tracking-[0.08em]'>
109+
Platform
110+
</span>
111+
<div className='mt-1.5 h-px bg-[var(--landing-bg-elevated)]' />
112+
</div>
113+
114+
<div className='grid grid-cols-2'>
115+
{PLATFORM.map((link) => (
116+
<DropdownLink key={link.label} link={link} />
117+
))}
118+
</div>
119+
</div>
120+
121+
<div className='w-px self-stretch bg-[var(--landing-bg-elevated)]' />
122+
123+
<div className='w-[160px] p-2'>
124+
<div className='mb-1 px-2.5 pt-1'>
125+
<span className='font-[430] font-season text-[11px] text-[var(--landing-text-subtle)] uppercase tracking-[0.08em]'>
126+
Explore
127+
</span>
128+
<div className='mt-1.5 h-px bg-[var(--landing-bg-elevated)]' />
129+
</div>
130+
131+
{EXPLORE.map((link) => {
132+
const Tag = link.external ? 'a' : Link
133+
const props = link.external
134+
? { href: link.href, target: '_blank' as const, rel: 'noopener noreferrer' }
135+
: { href: link.href }
136+
return (
137+
<Tag
138+
key={link.label}
139+
{...props}
140+
className='block rounded-[5px] px-2.5 py-1.5 font-[430] font-season text-[13px] text-white transition-colors hover:bg-[var(--landing-bg-elevated)]'
141+
>
142+
{link.label}
143+
</Tag>
144+
)
145+
})}
146+
</div>
147+
</div>
148+
)
149+
}

apps/sim/app/(landing)/integrations/[slug]/components/template-card-button.tsx

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@
22

33
import { useRouter } from 'next/navigation'
44
import { LandingPromptStorage } from '@/lib/core/utils/browser-storage'
5+
import { cn } from '@/lib/core/utils/cn'
56

67
interface TemplateCardButtonProps {
78
prompt: string
9+
className?: string
810
children: React.ReactNode
911
}
1012

11-
export function TemplateCardButton({ prompt, children }: TemplateCardButtonProps) {
13+
export function TemplateCardButton({ prompt, className, children }: TemplateCardButtonProps) {
1214
const router = useRouter()
1315

1416
function handleClick() {
@@ -17,11 +19,7 @@ export function TemplateCardButton({ prompt, children }: TemplateCardButtonProps
1719
}
1820

1921
return (
20-
<button
21-
type='button'
22-
onClick={handleClick}
23-
className='group flex w-full flex-col items-start rounded-lg border border-[var(--landing-border)] bg-[var(--landing-bg-card)] p-5 text-left transition-colors hover:border-[var(--landing-border-strong)] hover:bg-[var(--landing-bg-elevated)]'
24-
>
22+
<button type='button' onClick={handleClick} className={cn('w-full text-left', className)}>
2523
{children}
2624
</button>
2725
)

0 commit comments

Comments
 (0)