{title}
diff --git a/apps/sim/app/(landing)/components/features/components/features-rail/features-rail.test.tsx b/apps/sim/app/(landing)/components/features/components/features-rail/features-rail.test.tsx index 093047e0408..d72f6262d68 100644 --- a/apps/sim/app/(landing)/components/features/components/features-rail/features-rail.test.tsx +++ b/apps/sim/app/(landing)/components/features/components/features-rail/features-rail.test.tsx @@ -145,6 +145,39 @@ describe('FeaturesRail', () => { expect(mount(true).scrollLeft).toBe(SET) }) + it('keeps interactive controls keyboard-accessible only in the home copy', () => { + let activations = 0 + act(() => + root?.render( +-
+
- - +
-
+
{title}
diff --git a/apps/sim/app/(landing)/components/shared/cli-graphic/cli-graphic.module.css b/apps/sim/app/(landing)/components/shared/cli-graphic/cli-graphic.module.css index 06534ad2f36..496d29d7c4f 100644 --- a/apps/sim/app/(landing)/components/shared/cli-graphic/cli-graphic.module.css +++ b/apps/sim/app/(landing)/components/shared/cli-graphic/cli-graphic.module.css @@ -1,45 +1,209 @@ -@keyframes enter { - from { - opacity: 0; - transform: translateY(6px); +.scene { + position: absolute; + inset: 0; + container-type: size; +} + +.canvas { + position: absolute; + inset: 0; + isolation: isolate; + overflow: hidden; +} +.graph { + position: absolute; + left: 50%; + top: 18px; + width: 900px; + height: 280px; + transform: translateX(-50%); + transform-origin: top center; +} +.runIcon { + position: relative; + display: grid; + place-items: center; + width: 22px; + height: 22px; + transform: translate(8px, 1px); +} +.windowDots { + display: flex; + gap: 6px; +} +.windowDots i { + width: 9px; + height: 9px; + background: var(--text-subtle); + border-radius: 50%; +} +.inputFlag { + padding-left: 16px; + animation: arguments 12s steps(20, end) infinite; +} +.response { + margin-top: 10px; + color: var(--text-secondary); +} +.response > span { + display: block; + width: max-content; + max-width: 100%; + white-space: nowrap; +} +.started { + margin: 0; + animation: response-first 12s steps(34, end) infinite; +} +.running { + animation: response-second 12s steps(33, end) infinite; +} +.completed { + animation: response-third 12s steps(37, end) infinite; +} +@keyframes response-first { + 0%, + 41%, + 100% { + clip-path: inset(0 100% 0 0); + } + 51%, + 94% { + clip-path: inset(0); + } +} +@keyframes response-second { + 0%, + 52%, + 100% { + clip-path: inset(0 100% 0 0); + } + 62%, + 94% { + clip-path: inset(0); + } +} +@keyframes response-third { + 0%, + 63%, + 100% { + clip-path: inset(0 100% 0 0); } - to { - opacity: 1; - transform: translateY(0); + 72%, + 94% { + clip-path: inset(0); } } -.codeLine { - animation: enter 300ms ease-out both; +.terminal { + position: absolute; + z-index: 10; + right: 16px; + bottom: 16px; + left: 16px; + overflow: hidden; + border: 1px solid var(--border); + border-radius: 12px; + background: var(--surface-2); + box-shadow: var(--shadow-medium); +} + +.titlebar { + display: grid; + grid-template-columns: 1fr auto 1fr; + align-items: center; + gap: 10px; + height: 44px; + padding: 0 16px; + border-bottom: 1px solid var(--border); + background: var(--surface-1); } -.codeLine:nth-child(2) { - animation-delay: 300ms; +.transcript { + padding: 16px; + font-family: var(--font-geist-mono), ui-monospace, monospace; + font-size: 11px; + line-height: 20px; } -.codeLine:nth-child(3) { - animation-delay: 500ms; +.command, +.arguments { + display: block; + white-space: nowrap; + clip-path: inset(0 0 0 0); } -.codeLine:nth-child(4) { - animation-delay: 700ms; +.command { + animation: command 12s steps(19, end) infinite; } -.codeLine:nth-child(5) { - animation-delay: 900ms; +.arguments { + width: max-content; + animation: arguments 12s steps(23, end) infinite; } -.codeLine:nth-child(6) { - animation-delay: 1200ms; +.completed { + color: var(--text-primary); } -.composer { - animation: enter 400ms 1600ms cubic-bezier(0.22, 1, 0.36, 1) both; +@keyframes command { + 0%, + 8% { + clip-path: inset(0 100% 0 0); + } + 24%, + 94% { + clip-path: inset(0 0 0 0); + } + 100% { + clip-path: inset(0 100% 0 0); + } +} + +@keyframes arguments { + 0%, + 24% { + clip-path: inset(0 100% 0 0); + } + 40%, + 94% { + clip-path: inset(0 0 0 0); + } + 100% { + clip-path: inset(0 100% 0 0); + } } +@container (max-height: 350px) { + .graph { + top: 10px; + transform: translateX(-50%) scale(0.7); + } + .terminal { + right: 12px; + bottom: 12px; + left: 12px; + } + .titlebar { + padding: 0 10px; + gap: 6px; + } + .windowDots { + gap: 4px; + } + .windowDots i { + width: 7px; + height: 7px; + } + .transcript { + padding: 10px; + font-size: 10px; + line-height: 17px; + } +} @media (prefers-reduced-motion: reduce) { - .codeLine, - .composer { + .scene *, + .scene *::after { animation: none; } } diff --git a/apps/sim/app/(landing)/components/shared/cli-graphic/cli-graphic.tsx b/apps/sim/app/(landing)/components/shared/cli-graphic/cli-graphic.tsx index 5a8514d7bdf..680162f9503 100644 --- a/apps/sim/app/(landing)/components/shared/cli-graphic/cli-graphic.tsx +++ b/apps/sim/app/(landing)/components/shared/cli-graphic/cli-graphic.tsx @@ -1,72 +1,128 @@ +'use client' + import { cn } from '@sim/emcn' -import { ArrowUp, FolderCode, TerminalWindow } from '@sim/emcn/icons' +import { TerminalWindow } from '@sim/emcn/icons' +import { ThinkingLoader } from '@/components/ui/thinking-loader' +import { StageBlockCard } from '@/app/(landing)/components/hero/components/hero-platform-loop/stage-block-card' +import { STAGE_BLOCKS } from '@/app/(landing)/components/hero/components/hero-platform-loop/stage-data' +import { + horizontalHandleAnchors, + smoothStep, +} from '@/app/(landing)/components/hero/components/hero-visual/workflow-data' import styles from '@/app/(landing)/components/shared/cli-graphic/cli-graphic.module.css' -import type { CodeSegment } from '@/app/(landing)/components/shared/code-window-graphic/code-window-graphic' +import { EdgeFade } from '@/app/(landing)/components/shared/edge-fade' import { FeatureGraphicShell } from '@/app/(landing)/enterprise/components/feature-graphics/feature-graphic-shell' -import { FeaturePlatformPanel } from '@/app/(landing)/enterprise/components/feature-graphics/feature-platform-panel' -const CODE_LINES: readonly (readonly CodeSegment[])[] = [ - [{ text: 'sim workflows list' }], - [{ text: 'sim workflows run \\' }], - [{ text: ' "$WORKFLOW_ID" --manual \\', tone: 'muted' }], - [{ text: ' --input ', tone: 'muted' }, { text: '@ticket.json \\' }], - [{ text: ' --follow', tone: 'muted' }], - [{ text: 'sim logs list ' }, { text: '--limit 5', tone: 'muted' }], +const WORKFLOW_BLOCKS = [ + { + ...STAGE_BLOCKS[0], + id: 'cli-start', + name: 'Start', + x: 30, + y: 145, + position: 'left-[30px] top-[145px]', + }, + { + ...STAGE_BLOCKS[1], + id: 'cli-agent', + name: 'Support agent', + x: 325, + y: 65, + position: 'left-[325px] top-[65px]', + sentence: { + segments: ['Prompt', { subBlockId: 'model', noun: 'model' }], + values: { model: 'Claude Sonnet' }, + }, + }, + { + ...STAGE_BLOCKS[2], + id: 'cli-output', + name: 'Format reply', + x: 620, + y: 135, + position: 'left-[620px] top-[135px]', + }, ] -/** The original editor-and-composer composition, with supported CLI commands in a shell script. */ +/** A CLI run streams a sample reply while its support-agent node is thinking. */ export function CliGraphic() { return (
- -- - {CODE_LINES.map((line, index) => ( -- - {index + 1} - -- {line.map((segment, segmentIndex) => ( - - {segment.text} - - ))} -+
-
{CONTROLS.map(({ title, description, Mark }) => (
-