import { useState } from 'react' import { Collapse, Roll, Stage, type Act } from '../kit' import { MacPointer } from '../kit/cursors' import './contrasts.css' import './relationships.css' type State = { active: boolean; pressed: boolean } const initial: State = { active: false, pressed: false } const poster: State = { active: true, pressed: false } export const relationshipLessons = [ { id: 'horizontal-insert', title: 'An insertion moves what follows', note: 'Watch “Design review” as the check appears and disappears. The check needs room, and the existing label should travel with that room.', bad: 'The label jumps sideways', good: 'The label follows the opening space' }, { id: 'list-reflow', title: 'A new row carries the list', note: 'Follow Maya and Jon when Ana is added and removed. The new row arrives whole while the existing rows make room.', bad: 'Existing rows jump down and back', good: 'The list opens and closes around the row' }, { id: 'adjacent-action', title: 'A control carries the next action', note: 'Watch Settings while the first button changes width. Its position belongs to the same motion as the button’s edge.', bad: 'Settings jumps to the new edge', good: 'Settings travels with the changing width' }, { id: 'surface-resize', title: 'A popup resizes with its content', note: 'Watch the popup grow, return, then reverse before it finishes. The outline and content should belong to one continuous change.', bad: 'The outline jumps ahead of the content', good: 'The surface follows the same live motion' }, ] as const type LessonId = typeof relationshipLessons[number]['id'] async function change(a: Act, active: boolean, press = 100) { await a.set({ pressed: true }) await a.wait(press) await a.set({ pressed: false, active }) } async function script(a: Act) { await a.wait(1000) a.mark('insert') await change(a, true) await a.wait(1500) a.mark('remove') await change(a, false) await a.wait(1300) } async function surfaceScript(a: Act) { await script(a) a.mark('interrupt-open') await change(a, true) await a.wait(40) a.mark('interrupt-return') await change(a, false, 40) await a.wait(1200) } function Check() { return } function Pointer({ pressed }: { pressed: boolean }) { return } function Trigger({ state, label }: { state: State; label: string }) { return
{label}
} function Horizontal({ state, good }: { state: State; good: boolean }) { return
Design review
} function Person({ name, added = false }: { name: string; added?: boolean }) { return
{name[0]}{name}Reviewer
} function List({ state, good }: { state: State; good: boolean }) { return
Reviewers
} function Actions({ state, good }: { state: State; good: boolean }) { return
{state.active ? 'Disconnect account' : 'Connect'}
Settings {/* The input stays where it happened while the result changes size. */}
Connect
} function Surface({ state, good }: { state: State; good: boolean }) { return
Link access Anyone with the link can view.
} function Scene({ id, state, good }: { id: LessonId; state: State; good: boolean }) { if (id === 'horizontal-insert') return if (id === 'list-reflow') return if (id === 'adjacent-action') return return } export function RelationshipComparison({ lessonId }: { lessonId: string }) { const [revision, replay] = useState(0) const lesson = relationshipLessons.find(item => item.id === lessonId) if (!lesson) return null const height = lesson.id === 'list-reflow' ? 226 : lesson.id === 'surface-resize' ? 198 : 150 return

{lesson.title}

{lesson.note}

key={`${lesson.id}-${revision}`} width={704} height={height} compact={{ below: 704, width: 340, height: height * 2 + 16 }} initial={initial} poster={poster} script={lesson.id === 'surface-resize' ? surfaceScript : script} play="once" className="tc-stage"> {state =>
{[false, true].map(good =>
{good ? lesson.good : lesson.bad}
)}
}
}