mirror of
https://github.com/simstudioai/sim.git
synced 2026-09-24 15:45:35 +08:00
improvement(docs): restructure sidebar, align chrome, rename Mothership to Chat (#6296)
Sidebar: 11 separator groups become 5, with each module a collapsible folder that auto-opens on the active page. 61 always-visible rows drop to 16. Groups mirror the app's own nav (Chats/Workspace/Workflows) rather than inventing a taxonomy; Enterprise and Self-Hosting are hoisted out of Platform. Chrome: register the `hover-hover` variant, without which every @sim/emcn hover state silently compiled to nothing; restore the sidebar's Geist font stack; add 11 emcn tokens that were falling back to currentColor; adopt the named type scale; align row geometry, hover tokens and group labels with the app. Rename: mothership/ -> chat/ with redirects for the old URLs. Asset paths, the @mothership.sim.ai domain and the `mothership` log-trigger enum value are deliberately left alone -- they are CDN objects, a real domain, and a live product value. Also removes the page-type badge, drops the "Next" heading from the ToC, and lets FAQ rows open independently so expanding one no longer shifts the page.
This commit is contained in:
@@ -12,81 +12,40 @@ interface PageFooterProps {
|
||||
next?: PageNeighbour
|
||||
}
|
||||
|
||||
const SOCIAL_LINKS = [
|
||||
{
|
||||
href: 'https://x.com/simdotai',
|
||||
label: 'X (Twitter)',
|
||||
icon: 'M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z',
|
||||
},
|
||||
{
|
||||
href: 'https://github.com/simstudioai/sim',
|
||||
label: 'GitHub',
|
||||
icon: 'M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z',
|
||||
},
|
||||
{
|
||||
href: 'https://join.slack.com/t/sim-ott9864/shared_invite/zt-43lp8tc5v-0qrrqHGBKUsvQlpoouH~TA',
|
||||
label: 'Slack',
|
||||
icon: 'M5.042 15.165a2.528 2.528 0 0 1-2.52 2.523A2.528 2.528 0 0 1 0 15.165a2.527 2.527 0 0 1 2.522-2.52h2.52v2.52zM6.313 15.165a2.527 2.527 0 0 1 2.521-2.52 2.527 2.527 0 0 1 2.521 2.52v6.313A2.528 2.528 0 0 1 8.834 24a2.528 2.528 0 0 1-2.521-2.522v-6.313zM8.834 5.042a2.528 2.528 0 0 1-2.521-2.52A2.528 2.528 0 0 1 8.834 0a2.528 2.528 0 0 1 2.521 2.522v2.52H8.834zM8.834 6.313a2.528 2.528 0 0 1 2.521 2.521 2.528 2.528 0 0 1-2.521 2.521H2.522A2.528 2.528 0 0 1 0 8.834a2.528 2.528 0 0 1 2.522-2.521h6.312zM18.956 8.834a2.528 2.528 0 0 1 2.522-2.521A2.528 2.528 0 0 1 24 8.834a2.528 2.528 0 0 1-2.522 2.521h-2.522V8.834zM17.688 8.834a2.528 2.528 0 0 1-2.523 2.521 2.527 2.527 0 0 1-2.52-2.521V2.522A2.527 2.527 0 0 1 15.165 0a2.528 2.528 0 0 1 2.523 2.522v6.312zM15.165 18.956a2.528 2.528 0 0 1 2.523 2.522A2.528 2.528 0 0 1 15.165 24a2.527 2.527 0 0 1-2.52-2.522v-2.522h2.52zM15.165 17.688a2.527 2.527 0 0 1-2.52-2.523 2.526 2.526 0 0 1 2.52-2.52h6.313A2.527 2.527 0 0 1 24 15.165a2.528 2.528 0 0 1-2.522 2.523h-6.313z',
|
||||
},
|
||||
] as const
|
||||
|
||||
/**
|
||||
* Sequential page navigation. The destination name carries the meaning, so each
|
||||
* card shows it alone with a direction chevron — the chevron already says which
|
||||
* way you are going, and a "Previous"/"Next" label above the name only repeated
|
||||
* that. Social links live in the site footer directly below this.
|
||||
*/
|
||||
export function PageFooter({ previous, next }: PageFooterProps) {
|
||||
if (!previous && !next) return null
|
||||
|
||||
return (
|
||||
<div className='mt-12'>
|
||||
<div className='h-px w-full bg-[var(--border)]' />
|
||||
|
||||
{(previous || next) && (
|
||||
<div className='flex gap-2 py-3'>
|
||||
{previous ? (
|
||||
<Link
|
||||
href={previous.url}
|
||||
className='group flex flex-1 flex-col gap-1 rounded-lg px-3 py-3 transition-colors hover:bg-[var(--surface-3)]'
|
||||
>
|
||||
<span className='text-[var(--text-muted)] text-xs'>Previous</span>
|
||||
<span className='flex items-center gap-1.5 text-[var(--text-body)] text-sm transition-colors group-hover:text-[var(--text-primary)]'>
|
||||
<ChevronLeft className='size-3.5 shrink-0' />
|
||||
{previous.name}
|
||||
</span>
|
||||
</Link>
|
||||
) : (
|
||||
<div className='flex-1' />
|
||||
)}
|
||||
|
||||
{next ? (
|
||||
<Link
|
||||
href={next.url}
|
||||
className='group flex flex-1 flex-col items-end gap-1 rounded-lg px-3 py-3 transition-colors hover:bg-[var(--surface-3)]'
|
||||
>
|
||||
<span className='text-[var(--text-muted)] text-xs'>Next</span>
|
||||
<span className='flex items-center gap-1.5 text-[var(--text-body)] text-sm transition-colors group-hover:text-[var(--text-primary)]'>
|
||||
{next.name}
|
||||
<ChevronRight className='size-3.5 shrink-0' />
|
||||
</span>
|
||||
</Link>
|
||||
) : (
|
||||
<div className='flex-1' />
|
||||
)}
|
||||
</div>
|
||||
<div className='mt-12 flex gap-2 py-3'>
|
||||
{previous ? (
|
||||
<Link
|
||||
href={previous.url}
|
||||
className='flex flex-1 items-center gap-1.5 rounded-lg px-3 py-3 text-[var(--text-body)] text-sm transition-colors hover:bg-[var(--surface-active)]'
|
||||
>
|
||||
<ChevronLeft className='size-[14px] shrink-0 text-[var(--text-icon)]' />
|
||||
{previous.name}
|
||||
</Link>
|
||||
) : (
|
||||
<div className='flex-1' />
|
||||
)}
|
||||
|
||||
<div className='flex items-center gap-4 pt-4 pb-6'>
|
||||
{SOCIAL_LINKS.map((link) => (
|
||||
<Link
|
||||
key={link.label}
|
||||
href={link.href}
|
||||
target='_blank'
|
||||
rel='noopener noreferrer'
|
||||
aria-label={link.label}
|
||||
>
|
||||
<svg
|
||||
viewBox='0 0 24 24'
|
||||
className='size-[16px] fill-[var(--text-muted)] transition-colors hover:fill-[var(--text-icon)]'
|
||||
>
|
||||
<path d={link.icon} />
|
||||
</svg>
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
{next ? (
|
||||
<Link
|
||||
href={next.url}
|
||||
className='flex flex-1 items-center justify-end gap-1.5 rounded-lg px-3 py-3 text-[var(--text-body)] text-sm transition-colors hover:bg-[var(--surface-active)]'
|
||||
>
|
||||
{next.name}
|
||||
<ChevronRight className='size-[14px] shrink-0 text-[var(--text-icon)]' />
|
||||
</Link>
|
||||
) : (
|
||||
<div className='flex-1' />
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -40,18 +40,29 @@ function isActive(url: string, pathname: string, nested = true): boolean {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Rows mirror the app sidebar's chip pill: 30px tall, `rounded-lg`, `px-2`, 14px
|
||||
* at normal weight, `--text-body` at rest AND when active — only the background
|
||||
* moves, to `--surface-active`, then `--surface-6` when an active row is hovered.
|
||||
*
|
||||
* Height, horizontal padding, weight and color are additionally pinned in
|
||||
* `global.css` (`html #nd-sidebar a…`), which needs `!important` to beat
|
||||
* fumadocs' own sidebar rules and therefore also beats these utilities. Keep the
|
||||
* two in step: the classes here describe the intent and drive the mobile layout,
|
||||
* the stylesheet is what actually lands on desktop.
|
||||
*/
|
||||
const ITEM_BASE =
|
||||
'flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-[var(--text-muted)] text-sm transition-colors hover:bg-[var(--surface-active)] hover:text-[var(--text-body)]'
|
||||
const ITEM_ACTIVE_MOBILE = 'bg-[var(--surface-active)] font-medium text-[var(--text-primary)]'
|
||||
'flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-[var(--text-body)] text-sm transition-colors hover:bg-[var(--surface-active)]'
|
||||
const ITEM_ACTIVE_MOBILE = 'bg-[var(--surface-active)]'
|
||||
|
||||
const ITEM_DESKTOP =
|
||||
'lg:mb-[0.0625rem] lg:block lg:rounded-lg lg:px-2 lg:py-1.5 lg:font-normal lg:text-sm lg:leading-tight'
|
||||
'lg:mb-[0.0625rem] lg:block lg:rounded-lg lg:px-2 lg:font-normal lg:text-sm lg:leading-tight'
|
||||
const ITEM_TEXT = 'lg:text-[var(--text-body)]'
|
||||
const ITEM_HOVER = 'lg:hover:bg-[var(--surface-active)]'
|
||||
const ITEM_ACTIVE =
|
||||
'lg:bg-[var(--surface-active)] lg:font-normal lg:text-[var(--text-body)] lg:hover:bg-[var(--surface-6)]'
|
||||
|
||||
const FOLDER_TEXT = 'lg:text-[var(--text-body)] lg:font-medium'
|
||||
const FOLDER_TEXT = 'lg:text-[var(--text-body)] lg:font-normal'
|
||||
const FOLDER_HOVER = 'lg:hover:bg-[var(--surface-active)]'
|
||||
const FOLDER_ACTIVE =
|
||||
'lg:bg-[var(--surface-active)] lg:text-[var(--text-body)] lg:hover:bg-[var(--surface-6)]'
|
||||
@@ -133,9 +144,9 @@ export function SidebarFolder({ item, children }: { item: Folder; children: Reac
|
||||
data-active={active}
|
||||
className={cn(
|
||||
'flex flex-1 items-center gap-2 rounded-md px-2 py-1.5 text-sm transition-colors',
|
||||
'text-[var(--text-muted)] hover:bg-[var(--surface-active)] hover:text-[var(--text-body)]',
|
||||
'text-[var(--text-body)] hover:bg-[var(--surface-active)]',
|
||||
active && ITEM_ACTIVE_MOBILE,
|
||||
'lg:block lg:flex-1 lg:rounded-lg lg:px-2 lg:py-1.5 lg:text-sm lg:leading-tight',
|
||||
'lg:block lg:flex-1 lg:rounded-lg lg:px-2 lg:text-sm lg:leading-tight',
|
||||
FOLDER_TEXT,
|
||||
!active && FOLDER_HOVER,
|
||||
active && FOLDER_ACTIVE
|
||||
@@ -161,8 +172,8 @@ export function SidebarFolder({ item, children }: { item: Folder; children: Reac
|
||||
onClick={toggleOpen}
|
||||
className={cn(
|
||||
'flex flex-1 items-center gap-2 rounded-md px-2 py-1.5 text-sm transition-colors',
|
||||
'text-[var(--text-muted)] hover:bg-[var(--surface-active)]',
|
||||
'lg:flex lg:w-full lg:cursor-pointer lg:items-center lg:justify-between lg:rounded-lg lg:px-2 lg:py-1.5 lg:text-left lg:text-sm lg:leading-tight',
|
||||
'text-[var(--text-body)] hover:bg-[var(--surface-active)]',
|
||||
'lg:flex lg:w-full lg:cursor-pointer lg:items-center lg:justify-between lg:rounded-lg lg:px-2 lg:text-left lg:text-sm lg:leading-tight',
|
||||
FOLDER_TEXT,
|
||||
FOLDER_HOVER
|
||||
)}
|
||||
@@ -181,9 +192,7 @@ export function SidebarFolder({ item, children }: { item: Folder; children: Reac
|
||||
>
|
||||
<div className='overflow-hidden'>
|
||||
<div className='ml-4 flex flex-col gap-0.5 lg:hidden'>{children}</div>
|
||||
<ul className='mt-0.5 ml-2 hidden space-y-[0.0625rem] border-[var(--surface-active)] border-l pl-2.5 lg:block'>
|
||||
{children}
|
||||
</ul>
|
||||
<ul className='mt-0.5 ml-2 hidden space-y-[0.0625rem] pl-2.5 lg:block'>{children}</ul>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
@@ -191,25 +200,16 @@ export function SidebarFolder({ item, children }: { item: Folder; children: Reac
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Group label. Mirrors the app sidebar's section header: a 12px `--text-muted`
|
||||
* row at normal weight in sentence case, with the group's 16px top gap carried
|
||||
* by the label itself (the app's `SIDEBAR_SECTION_GAP_CLASS`). Groups are told
|
||||
* apart by that gap alone — the app draws no rule between them.
|
||||
*/
|
||||
export function SidebarSeparator({ item }: { item: Separator }) {
|
||||
return (
|
||||
<div
|
||||
data-separator
|
||||
className={cn('mt-5 mb-1.5 px-2', 'lg:relative lg:mt-0 lg:mb-1.5 lg:px-[13px] lg:pt-0')}
|
||||
>
|
||||
<div className='separator-divider hidden'>
|
||||
<div className='h-[20px]' />
|
||||
<div className='h-px bg-[var(--surface-active)]' />
|
||||
<div className='h-[20px]' />
|
||||
</div>
|
||||
<p
|
||||
className={cn(
|
||||
'font-medium text-[var(--text-muted)] text-xs',
|
||||
'lg:font-semibold lg:text-[var(--text-muted)] lg:text-micro lg:uppercase lg:tracking-[0.06em]'
|
||||
)}
|
||||
>
|
||||
{item.name}
|
||||
</p>
|
||||
<div data-separator className='mt-4 mb-1.5 px-2'>
|
||||
<p className='text-[var(--text-muted)] text-caption'>{item.name}</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ interface FooterItem {
|
||||
|
||||
const PRODUCT_LINKS: FooterItem[] = [
|
||||
{ label: 'Enterprise', href: `${SIM_SITE_URL}/enterprise`, external: true },
|
||||
{ label: 'Mothership', href: '/mothership' },
|
||||
{ label: 'Chat', href: '/chat' },
|
||||
{ label: 'Workflows', href: '/introduction' },
|
||||
{ label: 'Knowledge Base', href: '/knowledgebase' },
|
||||
{ label: 'Tables', href: '/tables' },
|
||||
|
||||
@@ -75,7 +75,7 @@ export function Navbar() {
|
||||
aria-current={isActive ? 'page' : undefined}
|
||||
{...(tab.external ? { target: '_blank', rel: 'noopener noreferrer' } : {})}
|
||||
className={cn(
|
||||
'-mb-px relative flex items-center border-b text-[14px] tracking-[-0.01em] transition-colors',
|
||||
'-mb-px relative flex items-center border-b text-sm tracking-[-0.01em] transition-colors',
|
||||
isActive
|
||||
? 'border-[var(--text-muted)] font-medium text-[var(--text-primary)]'
|
||||
: 'border-transparent font-normal text-[var(--text-muted)] hover:border-[var(--border-1)] hover:text-[var(--text-secondary)]'
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
import type { DocsPageType } from '@/lib/source'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
/**
|
||||
* Status-color mapping mirrored from the emcn `Badge` variants
|
||||
* (`apps/sim/components/emcn/components/badge/badge.tsx`) — `green`, `blue`,
|
||||
* `purple`, and `amber` over the shared `--badge-*` tokens.
|
||||
*/
|
||||
const CONFIG = {
|
||||
tutorial: {
|
||||
label: 'Tutorial',
|
||||
className: 'bg-[var(--badge-success-bg)] text-[var(--badge-success-text)]',
|
||||
},
|
||||
guide: {
|
||||
label: 'Guide',
|
||||
className: 'bg-[var(--badge-blue-bg)] text-[var(--badge-blue-text)]',
|
||||
},
|
||||
reference: {
|
||||
label: 'Reference',
|
||||
className: 'bg-[var(--badge-purple-bg)] text-[var(--badge-purple-text)]',
|
||||
},
|
||||
concept: {
|
||||
label: 'Concept',
|
||||
className: 'bg-[var(--badge-amber-bg)] text-[var(--badge-amber-text)]',
|
||||
},
|
||||
} as const satisfies Record<DocsPageType, { label: string; className: string }>
|
||||
|
||||
interface PageTypeBadgeProps {
|
||||
type: DocsPageType
|
||||
className?: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Small label that tells the reader which Diátaxis mode a page is — learning,
|
||||
* task, lookup, or understanding. Rendered only when a page declares `type`.
|
||||
* Chrome matches the emcn `Badge` status variants (md size).
|
||||
*/
|
||||
export function PageTypeBadge({ type, className }: PageTypeBadgeProps) {
|
||||
const config = CONFIG[type]
|
||||
if (!config) return null
|
||||
|
||||
return (
|
||||
<span
|
||||
className={cn(
|
||||
'inline-flex items-center gap-1.5 rounded-md px-[9px] py-0.5 font-medium font-season text-caption transition-colors',
|
||||
config.className,
|
||||
className
|
||||
)}
|
||||
>
|
||||
{config.label}
|
||||
</span>
|
||||
)
|
||||
}
|
||||
@@ -30,7 +30,7 @@ function FAQItemRow({
|
||||
type='button'
|
||||
onClick={onToggle}
|
||||
aria-expanded={isOpen}
|
||||
className='flex w-full cursor-pointer items-center gap-3 px-4 py-2.5 text-left font-medium text-[0.875rem] text-[var(--text-body)] transition-colors hover:bg-[var(--surface-3)]'
|
||||
className='flex w-full cursor-pointer items-center gap-3 px-4 py-2.5 text-left font-medium text-[var(--text-body)] text-sm transition-colors hover:bg-[var(--surface-active)]'
|
||||
>
|
||||
<ChevronRight
|
||||
className={cn(
|
||||
@@ -48,7 +48,7 @@ function FAQItemRow({
|
||||
}}
|
||||
>
|
||||
<div className='overflow-hidden'>
|
||||
<div className='px-4 pt-2 pb-2.5 pl-11 text-[0.875rem] text-[var(--text-secondary)] leading-relaxed'>
|
||||
<div className='px-4 pt-2 pb-2.5 pl-11 text-[var(--text-secondary)] text-sm leading-relaxed'>
|
||||
{item.answer}
|
||||
</div>
|
||||
</div>
|
||||
@@ -58,7 +58,21 @@ function FAQItemRow({
|
||||
}
|
||||
|
||||
export function FAQ({ items, title = 'Common Questions' }: FAQProps) {
|
||||
const [openIndex, setOpenIndex] = useState<number | null>(null)
|
||||
/**
|
||||
* Rows open independently rather than as a single-open accordion. Auto-closing
|
||||
* a sibling collapses content *above* the row being opened, which yanks that
|
||||
* row out from under the pointer — and since the FAQ is the last block on the
|
||||
* page, the shrinking document also clamps the scroll position and lurches the
|
||||
* whole viewport. Opening a row now only ever pushes content below it down.
|
||||
*/
|
||||
const [openIndices, setOpenIndices] = useState<ReadonlySet<number>>(() => new Set())
|
||||
|
||||
const toggle = (index: number) =>
|
||||
setOpenIndices((previous) => {
|
||||
const next = new Set(previous)
|
||||
if (!next.delete(index)) next.add(index)
|
||||
return next
|
||||
})
|
||||
|
||||
const faqSchema = {
|
||||
'@context': 'https://schema.org',
|
||||
@@ -88,8 +102,8 @@ export function FAQ({ items, title = 'Common Questions' }: FAQProps) {
|
||||
>
|
||||
<FAQItemRow
|
||||
item={item}
|
||||
isOpen={openIndex === index}
|
||||
onToggle={() => setOpenIndex(openIndex === index ? null : index)}
|
||||
isOpen={openIndices.has(index)}
|
||||
onToggle={() => toggle(index)}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
'use client'
|
||||
|
||||
import { useId } from 'react'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
interface SimLogoProps {
|
||||
@@ -32,107 +29,3 @@ export function SimWordmark({ className }: SimLogoProps) {
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Icon-only Sim mark, no wordmark text. Same brandbook icon geometry as
|
||||
* {@link SimLogoFull}'s icon, at its native square viewBox.
|
||||
*/
|
||||
export function SimLogoIcon({ className }: SimLogoProps) {
|
||||
const gradientId = `sim-logo-icon-gradient-${useId()}`
|
||||
|
||||
return (
|
||||
<svg
|
||||
viewBox='0 0 222 222'
|
||||
fill='none'
|
||||
xmlns='http://www.w3.org/2000/svg'
|
||||
className={cn('size-7', className)}
|
||||
aria-label='Sim'
|
||||
>
|
||||
<defs>
|
||||
<linearGradient
|
||||
id={gradientId}
|
||||
gradientUnits='userSpaceOnUse'
|
||||
x1='129.434'
|
||||
y1='129.266'
|
||||
x2='185.629'
|
||||
y2='185.33'
|
||||
>
|
||||
<stop offset='0' />
|
||||
<stop offset='1' stopOpacity='0' />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<path
|
||||
clipRule='evenodd'
|
||||
d='m107.822 93.7612c0 3.5869-1.419 7.0308-3.938 9.5668l-.361.364c-2.517 2.544-5.9375 3.966-9.4994 3.966h-80.5781c-7.42094 0-13.4455 6.06-13.4455 13.533v87.141c0 7.474 6.02456 13.534 13.4455 13.534h86.5167c7.4208 0 13.4378-6.06 13.4378-13.534v-81.587c0-3.326 1.31-6.517 3.647-8.871 2.33-2.347 5.499-3.667 8.802-3.667h81.928c7.421 0 13.437-6.059 13.437-13.533v-87.1407c0-7.47374-6.016-13.5333-13.437-13.5333h-86.517c-7.421 0-13.438 6.05956-13.438 13.5333zm26.256-75.2112h60.874c4.337 0 7.844 3.5393 7.844 7.9003v61.3071c0 4.3604-3.507 7.9003-7.844 7.9003h-60.874c-4.33 0-7.845-3.5399-7.845-7.9003v-61.3071c0-4.361 3.515-7.9003 7.845-7.9003z'
|
||||
fill='#33C482'
|
||||
fillRule='evenodd'
|
||||
/>
|
||||
<path
|
||||
d='m207.878 129.57h-64.324c-7.798 0-14.12 6.367-14.12 14.221v63.993c0 7.854 6.322 14.221 14.12 14.221h64.324c7.799 0 14.121-6.367 14.121-14.221v-63.993c0-7.854-6.322-14.221-14.121-14.221z'
|
||||
fill='#33C482'
|
||||
/>
|
||||
<path
|
||||
d='m207.878 129.266h-64.324c-7.798 0-14.12 6.366-14.12 14.221v63.992c0 7.854 6.322 14.22 14.12 14.22h64.324c7.799 0 14.121-6.366 14.121-14.22v-63.992c0-7.855-6.322-14.221-14.121-14.221z'
|
||||
fill={`url(#${gradientId})`}
|
||||
fillOpacity='0.2'
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Full Sim logo with icon and "Sim" text.
|
||||
* Uses the same SVG source as the landing page navbar for exact visual alignment.
|
||||
* The icon stays green (#33C482), text adapts to light/dark mode.
|
||||
*/
|
||||
export function SimLogoFull({ className }: SimLogoProps) {
|
||||
const gradientId = `sim-logo-full-gradient-${useId()}`
|
||||
|
||||
return (
|
||||
<svg
|
||||
viewBox='0 0 71 22'
|
||||
fill='none'
|
||||
xmlns='http://www.w3.org/2000/svg'
|
||||
className={cn('h-7 w-auto', className)}
|
||||
aria-label='Sim'
|
||||
>
|
||||
<defs>
|
||||
<linearGradient
|
||||
id={gradientId}
|
||||
gradientUnits='userSpaceOnUse'
|
||||
x1='171.406'
|
||||
y1='171.18'
|
||||
x2='245.831'
|
||||
y2='245.428'
|
||||
>
|
||||
<stop offset='0' />
|
||||
<stop offset='1' stopOpacity='0' />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
{/* Green icon — scaled to match landing logo proportions */}
|
||||
<g transform='scale(.07483)'>
|
||||
<path
|
||||
clipRule='evenodd'
|
||||
d='m142.79 124.17c0 4.75-1.88 9.31-5.22 12.67l-.48.48c-3.33 3.37-7.86 5.25-12.58 5.25h-106.71c-9.83 0-17.81 8.03-17.81 17.92v115.41c0 9.9 7.98 17.92 17.81 17.92h114.58c9.83 0 17.8-8.03 17.8-17.92v-108.05c0-4.41 1.74-8.63 4.83-11.75 3.09-3.11 7.28-4.86 11.66-4.86h108.5c9.83 0 17.8-8.02 17.8-17.92v-115.41c0-9.9-7.97-17.92-17.8-17.92h-114.58c-9.83 0-17.8 8.03-17.8 17.92zm34.77-99.61h80.62c5.74 0 10.39 4.69 10.39 10.46v81.19c0 5.77-4.64 10.46-10.39 10.46h-80.62c-5.73 0-10.39-4.69-10.39-10.46v-81.19c0-5.78 4.66-10.46 10.39-10.46z'
|
||||
fill='#33C482'
|
||||
fillRule='evenodd'
|
||||
/>
|
||||
<path
|
||||
d='m275.293 171.578h-85.187c-10.327 0-18.7 8.432-18.7 18.834v84.75c0 10.402 8.373 18.834 18.7 18.834h85.187c10.328 0 18.701-8.432 18.701-18.834v-84.75c0-10.402-8.373-18.834-18.701-18.834z'
|
||||
fill='#33C482'
|
||||
/>
|
||||
<path
|
||||
d='m275.293 171.18h-85.187c-10.327 0-18.7 8.432-18.7 18.834v84.749c0 10.402 8.373 18.833 18.7 18.833h85.187c10.328 0 18.701-8.431 18.701-18.833v-84.749c0-10.402-8.373-18.834-18.701-18.834z'
|
||||
fill={`url(#${gradientId})`}
|
||||
fillOpacity='0.2'
|
||||
/>
|
||||
</g>
|
||||
{/* "Sim" text — adapts to light/dark mode */}
|
||||
<g className='fill-[var(--text-primary)]'>
|
||||
<path d='M31.57 15.85h2.59c0 .71.26 1.28.78 1.71.52.41 1.22.61 2.1.61.96 0 1.7-.18 2.21-.55.52-.39.78-.9.78-1.53 0-.46-.14-.85-.43-1.16-.27-.31-.77-.56-1.49-.75l-2.47-.58c-1.25-.31-2.17-.78-2.79-1.42-.59-.64-.89-1.48-.89-2.52 0-.87.22-1.62.66-2.26.46-.64 1.08-1.13 1.87-1.48.8-.35 1.72-.52 2.76-.52s1.93.18 2.67.55c.77.37 1.36.88 1.78 1.53.44.66.67 1.44.69 2.35h-2.59c-.02-.73-.26-1.3-.72-1.71-.46-.41-1.1-.61-1.93-.61-.84 0-1.49.18-1.95.55-.46.37-.69.87-.69 1.51 0 .95.69 1.59 2.07 1.94l2.47.61c1.19.27 2.08.71 2.67 1.33.59.6.89 1.42.89 2.46 0 .89-.24 1.67-.72 2.35-.48.66-1.14 1.17-1.98 1.53-.82.35-1.8.52-2.93.52-1.65 0-2.96-.41-3.94-1.22-.98-.81-1.47-1.89-1.47-3.24z' />
|
||||
<path d='M44.51 19.96v-14.16c1.08.39 1.55.39 2.7 0v14.16zm1.32-15.09c-.48 0-.9-.17-1.26-.52-.34-.37-.52-.79-.52-1.27 0-.5.17-.93.52-1.27.36-.35.79-.52 1.26-.52.5 0 .92.17 1.26.52s.52.77.52 1.27c0 .48-.17.91-.52 1.27-.34.35-.77.52-1.26.52z' />
|
||||
<path d='M51.98 19.96h-2.7v-14.16h2.41v2.39c.29-.79.84-1.46 1.61-1.98.79-.54 1.73-.81 2.85-.81 1.25 0 2.28.34 3.1 1.01.82.68 1.36 1.57 1.61 2.69h-.49c.19-1.12.72-2.02 1.58-2.69.86-.68 1.93-1.01 3.19-1.01 1.61 0 2.87.47 3.79 1.42.92.95 1.38 2.24 1.38 3.88v9.26h-2.64v-8.6c0-1.12-.29-1.98-.86-2.58-.56-.62-1.31-.93-2.27-.93-.67 0-1.26.15-1.78.46-.5.29-.89.71-1.18 1.27-.29.56-.43 1.22-.43 1.97v8.4h-2.67v-8.63c0-1.12-.28-1.97-.83-2.55-.56-.6-1.31-.9-2.27-.9-.67 0-1.26.15-1.78.46-.5.29-.89.71-1.18 1.27-.29.54-.43 1.19-.43 1.94z' />
|
||||
</g>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ interface VideoProps {
|
||||
|
||||
export function Video({
|
||||
src,
|
||||
className = 'w-full rounded-xl border border-[var(--border)] overflow-hidden outline-none focus:outline-none',
|
||||
className = 'w-full',
|
||||
autoPlay = true,
|
||||
loop = true,
|
||||
muted = true,
|
||||
@@ -70,8 +70,9 @@ export function Video({
|
||||
width={width}
|
||||
height={height}
|
||||
className={cn(
|
||||
className,
|
||||
enableLightbox && 'cursor-pointer transition-opacity group-hover:opacity-[0.97]'
|
||||
'overflow-hidden rounded-xl border border-[var(--border)] outline-none focus:outline-none',
|
||||
enableLightbox && 'cursor-pointer transition-opacity group-hover:opacity-[0.97]',
|
||||
className
|
||||
)}
|
||||
src={isInView ? getAssetUrl(src) : undefined}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user