Skip to content

feat: 튜토리얼 6·9 스크린 디스코드 명령 시퀀스 CSS 애니메이션 (실데이터 픽스처 데모 PNG) - #60

Merged
mindongdong merged 5 commits into
mainfrom
feat/tutorial-doors-anim
Jul 4, 2026
Merged

feat: 튜토리얼 6·9 스크린 디스코드 명령 시퀀스 CSS 애니메이션 (실데이터 픽스처 데모 PNG)#60
mindongdong merged 5 commits into
mainfrom
feat/tutorial-doors-anim

Conversation

@mindongdong

@mindongdong mindongdong commented Jul 4, 2026

Copy link
Copy Markdown
Owner

요약

  • /tutorial 6번째(캐릭터 등록으로 열리는 명령들)·9번째(API 키로 열리는 명령들) 스크린의 src:null+ShotCollage 폴백을 디스코드 메시지 스타일 CSS 애니메이션으로 교체 — 작업지시서(grill 확정 결정 10건) 그대로 구현.
  • 신규 CommandSequenceDemo: / 타이핑 → 명령 팝업 → 파라미터 칩(전체 목록) → 값 선택(choice/멤버 팝업) → 전송 버튼 게이트(방문자 클릭, 미클릭 10초 후 자동 전송) → 봇 타이핑 도트 → 결과 임베드+PNG 상태머신. S6 7런(느림 3+빠름 4, 루프≈45s)·S9 4런(느림 2+빠름 2, 루프≈30s).
  • 결과 PNG는 QA 하네스 실실행 픽스처(가명화 완료 11런)를 render_demo_shots.py 확장으로 복원해 봇 실제 렌더러로 생성(demo-<run>.png 11종). 임베드 카피도 픽스처 messages[] 정본 그대로.
  • 봇 코드 무변경 · DiscordDemo/hero.css 랜딩 공용 무변경 · tutorial-steps.tsx 는 6·9 media 만 교체(명령 리터럴·드리프트 가드 형식 불변).

검증 (작업지시서 §6 전 항목)

  • npm run build + check-command-drift.mjs 그린, 루트 pytest 824 passed
  • 헤드리스 크롬 --virtual-time-budget 국면별 캡처: 팝업/칩/게이트/결과/값선택 팝업 (S6·S9)
  • 게이트 10s 자동 전송 확인(t=17s 결과 렌더) + CDP 클릭 수동 전송 확인(게이트 진입 4.6s → 클릭 → 5.8s 전송)
  • 모바일 500px · reduced-motion 정적 표시 · 라이트/다크 눈확인

Summary by CodeRabbit

  • New Features

    • Replaced two tutorial media sections with interactive command-sequence animations.
    • Added richer demo visuals for comparison, inventory, scheduler, and progression screens.
  • Documentation

    • Added a tutorial work-order page describing the updated animation flow and verification steps.
  • Bug Fixes

    • Improved the tutorial experience with reduced-motion support and cleaner on-screen behavior.
    • Updated demo screenshot generation to use stored fixtures for more consistent results.

site/scripts/fixtures/demo/*.json 11런을 복원(__type dataclass 마커·__bytes_b64
아이콘·ISO 날짜)해 site/public/shots/demo-<run>.png 로 생성. 기존 7종 무변경.
scheduler 는 캡처 3장 중 첫 캐릭터 카드 1장만 사용.
/ 타이핑→명령 팝업→파라미터 칩→값 선택(choice/멤버 팝업)→전송 게이트(클릭 대기,
10s 자동)→봇 타이핑→결과 임베드+데모 PNG 상태머신. S6 7런(느림3+빠름4)·S9 4런
(느림2+빠름2), 임베드 카피는 픽스처 messages[] 정본. reduced-motion 정적 표시.
DiscordDemo·hero.css 무변경, 스타일은 .mm-tut-seq-* 로 tutorial.css 에만 추가.
@vercel

vercel Bot commented Jul 4, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
maple-mate Ready Ready Preview, Comment Jul 4, 2026 10:18am

@coderabbitai

coderabbitai Bot commented Jul 4, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds a new interactive CommandSequenceDemo React component and CSS to animate Discord-style slash-command flows, replacing video media on tutorial screens 6 and 9. Introduces script data, JSON fixtures for demo renders, a fixture-driven PNG generation pipeline in render_demo_shots.py, and a work-order documentation page.

Changes

Command Sequence Animation Feature

Layer / File(s) Summary
Work-order documentation
docs/tutorial-anim-work-order.md
New documentation describing the animation replacement plan, decisions, per-screen scripts, design, traps, and verification checklist.
Run/script data model
site/components/commandSequenceScripts.tsx
Defines RunParam/Run types, embed helper components, parameter factories, and the S6_SCRIPT/S9_SCRIPT run data.
CommandSequenceDemo component
site/components/CommandSequenceDemo.tsx
Implements the phase-based animation state machine, UI primitives (popup, chips, input bar), send gate with auto-send, and reduced-motion static fallback.
Command sequence CSS
site/app/tutorial.css
Adds styles for the command popup, chips, input bar, send button, hint tooltip, shot output, and reduced-motion keyframe animations.
Tutorial steps wiring
site/data/tutorial-steps.tsx
Replaces video media for steps 5-2 and 6-3 with CommandSequenceDemo using scripts S6 and S9.
Demo fixture JSON data
site/scripts/fixtures/demo/*.json
Adds fixtures for exp, item, spec, potential, scheduler, starforce, and union runs with render args and message payloads.
Fixture-based PNG generation
site/scripts/render_demo_shots.py
Adds _revive, _load_render, build_from_fixture, and reworks main() to write demo-<run>.png for each fixture run.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant CommandSequenceDemo
  participant InputBar
  participant CommandPopup
  participant ValuePicker
  User->>CommandSequenceDemo: view tutorial step
  CommandSequenceDemo->>CommandPopup: show popup (typing phase)
  CommandSequenceDemo->>ValuePicker: render member/choice picker
  User->>InputBar: click send (or wait 10s auto-send)
  InputBar->>CommandSequenceDemo: advance gate phase
  CommandSequenceDemo->>CommandSequenceDemo: bot typing phase
  CommandSequenceDemo-->>User: render result (shot PNG) then loop
Loading
sequenceDiagram
  participant Main as render_demo_shots.main
  participant Fixture as build_from_fixture
  participant Revive as _revive
  participant Render as render_* function
  Main->>Fixture: for each run in _FIXTURE_RUNS
  Fixture->>Revive: parse fixture JSON args/kwargs
  Revive-->>Fixture: reconstructed dataclasses/bytes
  Fixture->>Render: invoke matched renderer
  Render-->>Fixture: PNG bytes
  Fixture-->>Main: write site/public/shots/demo-<run>.png
Loading

Estimated code review effort

Estimated code review effort: 4 (Complex) | ~60 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 제목이 튜토리얼 6·9 스크린의 디스코드 명령 시퀀스 CSS 애니메이션과 데모 PNG 변경을 정확히 요약합니다.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/tutorial-doors-anim

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (3)
site/data/tutorial-steps.tsx (1)

38-47: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

anim media type lacks an accessible/no-JS fallback contract.

The video variant requires an explicit fallback: React.ReactNode (used when src is null), but the new anim variant only carries node: React.ReactNode with no equivalent fallback field. Since CommandSequenceDemo renders its whole output as aria-hidden (see CommandSequenceDemo.tsx Lines 387, 424), screen-reader users get no accessible description of this tutorial media at all. Confirm the surrounding step copy (title/sub/commands) fully conveys the same information for steps 5-2 and 6-3, otherwise consider adding a visually-hidden text summary or aria-label for the animation.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@site/data/tutorial-steps.tsx` around lines 38 - 47, The new TutorialMedia
anim variant currently has no accessibility or no-JS fallback contract, unlike
the video variant with its explicit fallback. Update the TutorialMedia type and
the related rendering path that uses anim node so steps 5-2 and 6-3 still expose
a usable text alternative, either by confirming the surrounding step copy in
title/sub/commands fully covers the content or by adding an accessible summary
via visually-hidden text or an aria-label in the anim/CommandSequenceDemo flow.
site/components/CommandSequenceDemo.tsx (1)

54-60: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Reduced-motion detection is static and can flash before applying.

usePrefersReducedMotion reads matchMedia(...).matches once in a useEffect with initial state false, so: (1) it never reacts to the user toggling the OS/browser reduced-motion setting while the page is open, and (2) on first paint for a reduced-motion user, the animated variant briefly renders before the effect flips reduce to true.

♻️ Proposed fix — lazy init + live listener
 function usePrefersReducedMotion(): boolean {
-  const [reduce, setReduce] = React.useState(false)
-  React.useEffect(() => {
-    setReduce(window.matchMedia('(prefers-reduced-motion: reduce)').matches)
-  }, [])
+  const [reduce, setReduce] = React.useState(
+    () =>
+      typeof window !== 'undefined' &&
+      window.matchMedia('(prefers-reduced-motion: reduce)').matches,
+  )
+  React.useEffect(() => {
+    const mq = window.matchMedia('(prefers-reduced-motion: reduce)')
+    const onChange = () => setReduce(mq.matches)
+    mq.addEventListener('change', onChange)
+    return () => mq.removeEventListener('change', onChange)
+  }, [])
   return reduce
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@site/components/CommandSequenceDemo.tsx` around lines 54 - 60, The
reduced-motion hook is only sampling the media query once after mount, so it can
flash the animated state and never update when the setting changes. Update
usePrefersReducedMotion to initialize from
window.matchMedia('(prefers-reduced-motion: reduce)').matches during state
setup, and add a live change listener in the effect so the reduce state stays in
sync with OS/browser toggles. Keep the fix localized to usePrefersReducedMotion
in CommandSequenceDemo.
site/scripts/render_demo_shots.py (1)

444-457: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Isolate per-run failures in the generation loop.

If build_from_fixture(run) raises for any single run (e.g. unmapped renderer, missing fixture file), the whole main() invocation aborts and no further demo-*.png files are written. Wrapping each iteration to log-and-continue would make partial regeneration failures easier to diagnose without blocking the rest of the batch.

♻️ Proposed fix
     print("데모 애니 픽스처 복원 →")
     for run in _FIXTURE_RUNS:
-        _write(f"demo-{run}.png", build_from_fixture(run))
+        try:
+            _write(f"demo-{run}.png", build_from_fixture(run))
+        except Exception as exc:  # noqa: BLE001 - keep batch going, report clearly
+            print(f"  ✗ demo-{run}.png 생성 실패: {exc}")
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@site/scripts/render_demo_shots.py` around lines 444 - 457, The per-run
generation loop in main is not isolated, so a failure in build_from_fixture(run)
stops all remaining demo-*.png outputs. Update the loop over _FIXTURE_RUNS to
catch exceptions around each _write(f"demo-{run}.png", build_from_fixture(run))
call, log the failing run with enough context, and continue to the next run.
Keep the existing main and build_from_fixture symbols as the entry points for
locating the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@site/components/CommandSequenceDemo.tsx`:
- Around line 239-256: The send control in CommandSequenceDemo is still tabbable
inside an aria-hidden demo, which can leave keyboard focus on an element hidden
from assistive tech. Update the InputBar/send button behavior so it stays
tabIndex={-1} while the surrounding demo remains aria-hidden, or remove
aria-hidden from the wrapper if this section is intended to be interactive; use
the CommandSequenceDemo and InputBar send button logic to locate the change.

---

Nitpick comments:
In `@site/components/CommandSequenceDemo.tsx`:
- Around line 54-60: The reduced-motion hook is only sampling the media query
once after mount, so it can flash the animated state and never update when the
setting changes. Update usePrefersReducedMotion to initialize from
window.matchMedia('(prefers-reduced-motion: reduce)').matches during state
setup, and add a live change listener in the effect so the reduce state stays in
sync with OS/browser toggles. Keep the fix localized to usePrefersReducedMotion
in CommandSequenceDemo.

In `@site/data/tutorial-steps.tsx`:
- Around line 38-47: The new TutorialMedia anim variant currently has no
accessibility or no-JS fallback contract, unlike the video variant with its
explicit fallback. Update the TutorialMedia type and the related rendering path
that uses anim node so steps 5-2 and 6-3 still expose a usable text alternative,
either by confirming the surrounding step copy in title/sub/commands fully
covers the content or by adding an accessible summary via visually-hidden text
or an aria-label in the anim/CommandSequenceDemo flow.

In `@site/scripts/render_demo_shots.py`:
- Around line 444-457: The per-run generation loop in main is not isolated, so a
failure in build_from_fixture(run) stops all remaining demo-*.png outputs.
Update the loop over _FIXTURE_RUNS to catch exceptions around each
_write(f"demo-{run}.png", build_from_fixture(run)) call, log the failing run
with enough context, and continue to the next run. Keep the existing main and
build_from_fixture symbols as the entry points for locating the change.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b485acd9-b8ec-47a3-8972-bc596615479a

📥 Commits

Reviewing files that changed from the base of the PR and between 697723b and bc151d8.

⛔ Files ignored due to path filters (11)
  • site/public/shots/demo-exp_challengers.png is excluded by !**/*.png
  • site/public/shots/demo-exp_main.png is excluded by !**/*.png
  • site/public/shots/demo-exp_target.png is excluded by !**/*.png
  • site/public/shots/demo-item_weapon.png is excluded by !**/*.png
  • site/public/shots/demo-mychar_spec.png is excluded by !**/*.png
  • site/public/shots/demo-potential_30d.png is excluded by !**/*.png
  • site/public/shots/demo-scheduler.png is excluded by !**/*.png
  • site/public/shots/demo-spec_three.png is excluded by !**/*.png
  • site/public/shots/demo-starforce_rand.png is excluded by !**/*.png
  • site/public/shots/demo-starforce_target.png is excluded by !**/*.png
  • site/public/shots/demo-union_all.png is excluded by !**/*.png
📒 Files selected for processing (17)
  • docs/tutorial-anim-work-order.md
  • site/app/tutorial.css
  • site/components/CommandSequenceDemo.tsx
  • site/components/commandSequenceScripts.tsx
  • site/data/tutorial-steps.tsx
  • site/scripts/fixtures/demo/exp_challengers.json
  • site/scripts/fixtures/demo/exp_main.json
  • site/scripts/fixtures/demo/exp_target.json
  • site/scripts/fixtures/demo/item_weapon.json
  • site/scripts/fixtures/demo/mychar_spec.json
  • site/scripts/fixtures/demo/potential_30d.json
  • site/scripts/fixtures/demo/scheduler.json
  • site/scripts/fixtures/demo/spec_three.json
  • site/scripts/fixtures/demo/starforce_rand.json
  • site/scripts/fixtures/demo/starforce_target.json
  • site/scripts/fixtures/demo/union_all.json
  • site/scripts/render_demo_shots.py

Comment on lines +239 to +256
<button
type="button"
className={`mm-tut-seq-send${gate ? ' is-armed' : ''}`}
onClick={gate ? onSend : undefined}
tabIndex={gate ? 0 : -1}
aria-label="전송"
>
<SendHorizontal size={16} strokeWidth={2.4} aria-hidden />
</button>
{gate ? (
<span className="mm-tut-seq-hint" aria-hidden>
눌러서 전송해 보세요
</span>
) : null}
</div>
)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Map the component structure first
ast-grep outline site/components/CommandSequenceDemo.tsx --view expanded

# Find aria-hidden, tabIndex, and send button usage in the file
rg -n 'aria-hidden|tabIndex|mm-tut-seq-send|InputBar|SendHorizontal|fallback|video' site/components/CommandSequenceDemo.tsx

# Read the relevant sections around the reported lines
sed -n '220,270p' site/components/CommandSequenceDemo.tsx
sed -n '360,470p' site/components/CommandSequenceDemo.tsx

Repository: mindongdong/maple-mate

Length of output: 6160


Keep the send button out of the aria-hidden demo.
CommandSequenceDemo hides the whole chat subtree from assistive tech, but InputBar still makes the send button tabbable when gate is true (tabIndex={0}). That leaves keyboard focus on a control that AT treats as hidden; keep it tabIndex={-1} (or remove aria-hidden from the wrapper if this demo is meant to be interactive).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@site/components/CommandSequenceDemo.tsx` around lines 239 - 256, The send
control in CommandSequenceDemo is still tabbable inside an aria-hidden demo,
which can leave keyboard focus on an element hidden from assistive tech. Update
the InputBar/send button behavior so it stays tabIndex={-1} while the
surrounding demo remains aria-hidden, or remove aria-hidden from the wrapper if
this section is intended to be interactive; use the CommandSequenceDemo and
InputBar send button logic to locate the change.

@mindongdong
mindongdong merged commit ff9a583 into main Jul 4, 2026
6 checks passed
@mindongdong
mindongdong deleted the feat/tutorial-doors-anim branch July 4, 2026 10:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant