Files
wehub-resource-sync d25d482dc2
CI / Migrate Dev DB (push) Has been skipped
CI / Detect Version (push) Has been cancelled
CI / Migrate DB (push) Has been cancelled
CI / Build Dev ECR (./docker/app.Dockerfile, ECR_APP) (push) Has been cancelled
CI / Build Dev ECR (./docker/db.Dockerfile, ECR_MIGRATIONS) (push) Has been cancelled
CI / Build Dev ECR (./docker/pii.Dockerfile, ECR_PII) (push) Has been cancelled
CI / Build Dev ECR (./docker/realtime.Dockerfile, ECR_REALTIME) (push) Has been cancelled
CI / Deploy Trigger.dev (Dev) (push) Has been cancelled
CI / Build AMD64 (./docker/app.Dockerfile, ECR_APP, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build AMD64 (./docker/db.Dockerfile, ECR_MIGRATIONS, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build AMD64 (./docker/pii.Dockerfile, ECR_PII, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build AMD64 (./docker/realtime.Dockerfile, ECR_REALTIME, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/app.Dockerfile, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/db.Dockerfile, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/pii.Dockerfile, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/realtime.Dockerfile, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Check Docs Changes (push) Has been cancelled
CI / Process Docs (push) Has been cancelled
CI / Create GitHub Release (push) Has been cancelled
CI / Test and Build (push) Has been cancelled
Publish CLI Package / publish-npm (push) Has been cancelled
Publish Python SDK / publish-pypi (push) Has been cancelled
Publish TypeScript SDK / publish-npm (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:20:55 +08:00

300 lines
11 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import type { CSSProperties } from 'react'
import { cn } from '@sim/emcn'
import { ThinkingLoader } from '@/components/ui'
import { FeatureGraphicShell } from '@/app/(landing)/enterprise/components/feature-graphics/feature-graphic-shell'
import styles from '@/app/(landing)/enterprise/components/feature-graphics/operations-teams-graphic.module.css'
/**
* Fixed pixel canvas the switchboard is drawn on, centered inside the
* shell. Kept to 280px wide (chips reaching only x 32250) so every chip
* stays inside the tile's visible area even at the narrowest three-up
* tile width (~274px visible at 1024), and 248px tall — the tallest
* canvas that clears the slot's shortest inner box (~257px at 1024 after
* bottom-bleed compensation) so the staggered top pills never clip while
* the wires keep long vertical runs.
*/
const CANVAS = { WIDTH: 280, HEIGHT: 248 } as const
/**
* The ThinkingLoader's light-grey material (its dark-surface theme from
* `thinking-loader.module.css`), asserted inline exactly as the deploy
* tile's Deploy button does — the always-light landing would otherwise
* ink the loader dark, invisible on the dark tile ground showing through
* the outlined router hub.
*/
const ROUTER_LOADER_INK = {
'--tl-grad-inner': '#a7a7a7',
'--tl-grad-outer': '#d6d6d6',
'--tl-glow': 'rgba(255, 255, 255, 0.9)',
} as CSSProperties
interface Port {
/** Tailwind classes positioning the size-2 port dot, centered on the port's canvas x/y. */
dotClass: string
/** Tailwind classes placing the tag's center on the port's canvas x, above/below its dot. */
chipClass: string
/** Tool name rendered as an outlined tag beside the port. */
label: string
/** CSS-module animation class driving this tag's white connect-fill on its scheduled phases. */
fillClass: string
}
/**
* Inbound ops tools across the top, staggered like a constellation rather
* than a rank: Zendesk rides highest on the center axis (x 140), Gmail
* sits lowest at the left (x 56), Sheets between at the right (x 224).
*/
const SOURCES: readonly Port[] = [
{
dotClass: 'top-[48px] left-[52px]',
chipClass: 'top-[32px] left-[56px]',
label: 'Gmail',
fillClass: styles.fillSrcC,
},
{
dotClass: 'top-[28px] left-[136px]',
chipClass: 'top-[12px] left-[140px]',
label: 'Zendesk',
fillClass: styles.fillSrcA,
},
{
dotClass: 'top-[38px] left-[220px]',
chipClass: 'top-[22px] left-[224px]',
label: 'Sheets',
fillClass: styles.fillSrcB,
},
] as const
/**
* Outbound destinations mirrored below, staggered the same way: Slack at
* the left (x 56), Salesforce hanging lowest on the center axis (x 140),
* Jira highest at the right (x 224).
*/
const DESTINATIONS: readonly Port[] = [
{
dotClass: 'top-[192px] left-[52px]',
chipClass: 'top-[216px] left-[56px]',
label: 'Slack',
fillClass: styles.fillDstA,
},
{
dotClass: 'top-[212px] left-[136px]',
chipClass: 'top-[236px] left-[140px]',
label: 'Salesforce',
fillClass: styles.fillDstC,
},
{
dotClass: 'top-[202px] left-[220px]',
chipClass: 'top-[226px] left-[224px]',
label: 'Jira',
fillClass: styles.fillDstB,
},
] as const
/**
* Wires from each source port gathering into the router hub's top pole
* (140, 93) — all three terminate at the same point so they read as a
* tied bundle feeding the agent, with vertical tangents at both ends
* (the access tile's edge geometry) and long vertical runs so each curve
* travels before it arrives.
*/
const IN_PATHS = {
gmail: 'M 56 52 C 56 74 140 66 140 93',
zendesk: 'M 140 32 L 140 93',
sheets: 'M 224 42 C 224 70 140 64 140 93',
} as const
/**
* Wires fanning out from the router hub's bottom pole (140, 155) — the
* shared origin splitting to each destination, echoing the deploy tile's
* single pipeline branching.
*/
const OUT_PATHS = {
slack: 'M 140 155 C 140 182 56 174 56 196',
salesforce: 'M 140 155 L 140 216',
jira: 'M 140 155 C 140 184 224 178 224 206',
} as const
/** Faint-ink stroke for the resting wires (the deploy tile's guide-line grey, quieter). */
const QUIET_STROKE = 'color-mix(in srgb, var(--text-muted-inverse) 28%, transparent)'
/** Shared 1px outline ink for the tags, port dots, and router hub ring. */
const OUTLINE_INK = 'border-[color:color-mix(in_srgb,var(--text-muted-inverse)_45%,transparent)]'
/** Shared SVG props for a resting wire. */
const WIRE_PROPS = { stroke: QUIET_STROKE, strokeWidth: '1' } as const
/** Shared SVG props for a traveling white request-pulse overlay on a wire. */
const PULSE_PROPS = {
pathLength: 1,
stroke: 'var(--text-inverse)',
strokeWidth: '1.25',
strokeLinecap: 'round',
} as const
/** An outlined integration tag whose white connect-fill crossfades in on its scheduled phases. */
function PortTag({ port }: { port: Port }) {
return (
<span
className={cn('-translate-x-1/2 -translate-y-1/2 absolute whitespace-nowrap', port.chipClass)}
>
<span
className={cn(
'relative flex h-5 items-center overflow-hidden rounded-md border bg-transparent px-1.5 font-medium text-[var(--text-muted-inverse)] text-caption',
OUTLINE_INK
)}
>
{port.label}
<span
className={cn(
'absolute inset-0 flex items-center bg-[var(--white)] px-1.5 text-[var(--text-primary)] opacity-0',
port.fillClass
)}
>
{port.label}
</span>
</span>
</span>
)
}
/**
* Operations automation told as a vertical switchboard — the access tile's
* top-to-bottom composition (sources above, curved bezier edges flowing
* down to what they feed) in the dark tiles' ink: three ops tools wired in
* across the top (Gmail, Zendesk, Sheets), an outlined circular router hub
* at center — the agent — and three destinations wired out below (Slack,
* Salesforce, Jira). Both rows stagger their tag heights into a loose
* constellation, giving each wire its own long arc instead of ranking the
* tags into flat rows. Every element is drawn in the same outlined
* language: the six tool tags rest as transparent pills with 1px light
* hairline borders and light-grey ink, the hub is a transparent circle
* with the same hairline ring, and the wires are 1px curved SVG paths
* with vertical tangents (the access tile's edge geometry) gathering into
* the hub's top pole and fanning from its bottom pole — a tied bundle in,
* a split out.
*
* Inside the hub, the platform's gooey {@link ThinkingLoader} runs its
* default full morph cycle (no pinned variant, unlike the deploy button's
* `relay`) wearing the deploy button's exact light-grey ink override, so
* the page's two dark-tile loaders read as the same material — the agent
* visibly churning through work between dispatches. The loader stops
* cycling on its own under `prefers-reduced-motion`.
*
* Motion (from `operations-teams-graphic.module.css`, one shared 16s
* timeline of four 4s route phases — Zendesk→Slack, Sheets→Jira,
* Gmail→Salesforce, Zendesk→Jira — a precomputed shuffle so the routing
* feels varied): in each phase the source tag's white filled state
* crossfades in over its outline (ink flipping dark with it), a white
* pulse falls down its wire into the router — which blooms the family's
* ring pulse while the agent classifies — then out the bottom pole to
* the destination tag, whose fill crossfades in as the route connects.
* Both ends hold briefly, fade back to outlined, and the next pair
* begins. Everything is static and outlined under
* `prefers-reduced-motion`.
*
* The feature tile's visual slot bleeds `2rem` right and bottom (`1.5rem`
* under `max-lg`) but not left or top, so the canvas sits inside a
* matching right- and bottom-padded box to land on the tile's visible
* center. The fixed-size canvas is centered with a transform (`left-1/2`
* + `-translate-x-1/2`, the standards tile's approach) so at narrow tile
* widths it keeps its wiring geometry and overflows both edges equally
* instead of drifting. On the narrow grid bands where the tile drops
* below the canvas width (small two-column screens and the 3-up row just
* past `lg`) the canvas scales down via transform so the outer tool pills
* are never cropped.
*/
export function OperationsTeamsGraphic() {
return (
<FeatureGraphicShell>
<div aria-hidden='true' className='absolute inset-0 pr-8 pb-8 max-lg:pr-6 max-lg:pb-6'>
<div className='relative h-full'>
<div className='-translate-x-1/2 -translate-y-1/2 absolute top-1/2 left-1/2 h-[248px] w-[280px] max-sm:scale-100 max-md:scale-[0.85] lg:max-[1180px]:scale-[0.85]'>
<svg
className='absolute inset-0'
fill='none'
viewBox={`0 0 ${CANVAS.WIDTH} ${CANVAS.HEIGHT}`}
width={CANVAS.WIDTH}
height={CANVAS.HEIGHT}
>
<path d={IN_PATHS.gmail} {...WIRE_PROPS} />
<path d={IN_PATHS.zendesk} {...WIRE_PROPS} />
<path d={IN_PATHS.sheets} {...WIRE_PROPS} />
<path d={OUT_PATHS.slack} {...WIRE_PROPS} />
<path d={OUT_PATHS.salesforce} {...WIRE_PROPS} />
<path d={OUT_PATHS.jira} {...WIRE_PROPS} />
<path
d={IN_PATHS.zendesk}
className={cn(styles.pulse, styles.pulseInA)}
{...PULSE_PROPS}
/>
<path
d={IN_PATHS.sheets}
className={cn(styles.pulse, styles.pulseInB)}
{...PULSE_PROPS}
/>
<path
d={IN_PATHS.gmail}
className={cn(styles.pulse, styles.pulseInC)}
{...PULSE_PROPS}
/>
<path
d={OUT_PATHS.slack}
className={cn(styles.pulse, styles.pulseOutA)}
{...PULSE_PROPS}
/>
<path
d={OUT_PATHS.jira}
className={cn(styles.pulse, styles.pulseOutB)}
{...PULSE_PROPS}
/>
<path
d={OUT_PATHS.salesforce}
className={cn(styles.pulse, styles.pulseOutC)}
{...PULSE_PROPS}
/>
</svg>
{SOURCES.map((port) => (
<span key={port.label}>
<span
className={cn(
'absolute size-2 rounded-full border bg-[var(--text-secondary)]',
OUTLINE_INK,
port.dotClass
)}
/>
<PortTag port={port} />
</span>
))}
{DESTINATIONS.map((port) => (
<span key={port.label}>
<span
className={cn(
'absolute size-2 rounded-full border bg-[var(--text-secondary)]',
OUTLINE_INK,
port.dotClass
)}
/>
<PortTag port={port} />
</span>
))}
<div
className={cn(
'absolute top-[93px] left-[109px] flex size-[62px] items-center justify-center rounded-full border',
OUTLINE_INK,
styles.routerBloom
)}
>
<ThinkingLoader size={36} style={ROUTER_LOADER_INK} />
</div>
</div>
</div>
</div>
</FeatureGraphicShell>
)
}