Skip to content

fix(gui): add narrow-screen warning + lift min-width below 768px (Phase 1 of #572)#577

Merged
takaokouji merged 7 commits into
developfrom
fix/issue-572-responsive-phase-1
Apr 29, 2026
Merged

fix(gui): add narrow-screen warning + lift min-width below 768px (Phase 1 of #572)#577
takaokouji merged 7 commits into
developfrom
fix/issue-572-responsive-phase-1

Conversation

@takaokouji
Copy link
Copy Markdown

Summary

iOS Safari など狭幅画面で「スプライトを選ぶ」ボタンが画面外でタップ不能になる問題 (#572) の Phase 1 緊急修正

  • min-width: 1024px@media (min-width: 768px) で囲み、iPhone 等の狭幅画面では適用しないようにする
  • 狭幅画面 (< 768px) のみ警告バナーを表示し、本格的な編集は PC・タブレット推奨であることを案内
  • バナーは [✕ 閉じる] で localStorage に dismissed フラグを記録、再表示しない

Phase 2 (提案 C: ボトムタブ + ステージ全画面プレビュー + ブロックパレットドロワー) は別 Issue / 別 PR で対応する。

設計の経緯

  • 設計検討メモ: notes/issue-572-responsive-ux-design.md (git 管理外、後に ADR としてまとめる予定)
  • ユーザー方針:
    • スマホ = 鑑賞・微調整・プレゼンモード。本格編集は PC
    • iPhone (390px) を最優先、iPad portrait (768px) は別 Phase で PC レイアウト維持
    • upstream 追従コスト最小化 (新規ジェスチャ・大きなインデント変更・upstream への分岐多数追加は避ける)

変更点

upstream ファイル (Smalruby マーカーで囲む)

  • src/playground/index.cssmin-width: 1024px / min-height: 600px@media (min-width: 768px) で囲んだだけ。狭幅では適用しない
  • src/components/gui/gui.jsx<NarrowScreenWarning /> を 1 行追加 (modal block と同じ場所)。インデント変更・分岐追加なし

Smalruby 固有ファイル (新規)

  • src/components/narrow-screen-warning/narrow-screen-warning.{jsx,css} — バナー本体 (matchMedia('(max-width: 767px)') で検知 + localStorage で dismiss 記録)
  • src/components/narrow-screen-warning/index.js — re-export
  • test/unit/components/narrow-screen-warning.test.jsx — 5 ユニットテスト (RTL + jest)

ロケール (3 言語、2 メッセージ)

  • ja / ja-Hira / en に gui.narrowScreenWarning.messagegui.narrowScreenWarning.close を追加

メタファイル

  • .prettierignore / smalruby-prettier-files.md (scratch-gui) — 新規ファイルを Prettier ホワイトリストに追加
  • smalruby-markers.md — 新規マーカー 2 件を一覧に追加

検証

ユニットテスト (jest, 5 件)

  • 狭幅 + 未 dismiss → 表示
  • 広幅 → 非表示
  • 既に dismiss → 非表示
  • 閉じるボタン → 非表示 + localStorage に true
  • viewport 変化 (matchMedia) で表示が切り替わる

Playwright (Chromium DevTools)

Viewport min-width バナー 結果
390×844 (iPhone 14) 0px (適用解除) 表示 body-wrapper 内 scroll でスプライト追加ボタンに到達可能
768×1024 (iPad portrait) 1024px 非表示 PC レイアウト維持
1280×800 (PC) 1024px 非表示 upstream と同等
  • 閉じるボタン → 即座に非表示、リロードしても再表示されない
  • ja / ja-Hira / en の 3 言語で正しく表示される
  • ja: 📱 狭い画面では一部の操作がしづらい場合があります。本格的な編集はパソコンやタブレットを推奨します。 / 閉じる
  • en: 📱 Some operations may be hard to use on narrow screens. We recommend using a PC or tablet for full editing. / Close

Test plan

  • ユニットテスト 5/5 緑
  • npm run test:lint 通過 (このブランチで追加した部分について。pre-existing import-x/no-unresolved は別件)
  • npm run format:check 通過
  • Playwright で 3 つの viewport 検証
  • 閉じるボタンの localStorage 動作確認
  • ja / en ロケールでバナー表示確認
  • CI green (push 後)

Related

🤖 Generated with Claude Code

…se 1)

iOS Safari など狭幅画面で「スプライトを選ぶ」ボタンが画面外に出てタップ
できない問題 (issue #572) の Phase 1 対応。

- playground/index.css の min-width 1024px / min-height 600px を
  @media (min-width: 768px) で囲み、iPhone 等では適用しない
- 新規 NarrowScreenWarning コンポーネントを追加 (matchMedia で 767px 以下
  を検知、localStorage smalruby:narrowScreenWarningDismissed で再表示抑止)
- gui.jsx に 1 行マウント (Smalruby マーカーで囲む)
- ja / ja-Hira / en の 2 メッセージ追加

Phase 2 (ボトムタブ + ステージ全画面プレビュー + ブロックパレットドロワー)
は別 Issue / 別 PR で対応する。

Refs #572

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown

takaokouji and others added 6 commits April 29, 2026 20:06
…ays in viewport

Chrome の mobile emulator (DevTools) で iPhone サイズ 390x844 を選んだ際、
警告バナーが viewport 下端ではなく document 末尾の遥か下 (y=1036+) に
配置されてしまう問題を修正。

原因:
- 狭幅 viewport では body 内部のコンテンツ (Scratch レイアウトは 1024px+ 想定)
  が body を横方向に overflow させて scrollWidth=501 になっていた
- Chrome の layout viewport がこの overflow に追従して 501 に拡張
- position: fixed の containing block は layout viewport なので、
  バナーの left:0; right:0 が幅 501 に伸び、document 全体の中で位置決め
  されてしまっていた

修正:
- @media (max-width: 767px) で html / body / .app に
  overflow-x: hidden + max-width: 100vw を当て、layout viewport を viewport
  幅にロック
- 内部スクロールは元々 overflow-x: auto を持つ gui_body-wrapper が引き続き
  担うので、スプライトを選ぶボタンへの到達性は維持

合わせて:
- バナー DOM を Portal で document.body 直下に飛ばす
  (将来的に upstream が GUI 祖先要素に transform 等を入れた際の影響を予防)
- safe-area-inset-{bottom,left,right} を padding に反映
- バナーメッセージを 1 行に圧縮 (3 言語)、フォント / padding を縮小

Refs #572

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Phase 1 のレスポンシブ対応で body の overflow-x を hidden にした副作用で、
メニューバー右端 (デバッグ・ヘルプアイコン等) に到達できなくなった
(issue #572 ハマり経過の中で利用者から指摘あり)。

修正:
- @media (max-width: 767px) で menu-bar 自身に overflow-x: auto を当てる
- スクロールバー UI は scrollbar-width: none と ::-webkit-scrollbar で
  非表示にする (タッチ・ホイールでスクロール自体は可能)
- 編集領域 (gui_body-wrapper) と独立してスクロールする構成

CSS modules のクラス命名 (`menu-bar_menu-bar_<hash>`) に対する部分一致
セレクターを使用。upstream が menu-bar.css の `.menu-bar` クラス名を
変えない限り動作する。

Refs #572

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
issue #572 Phase 1 では狭幅画面 (iPhone 等) では編集が事実上できないため、
ユーザー要望により毎回バナーを案内する形に変更:

- localStorage への永続化 (smalruby:narrowScreenWarningDismissed) を撤廃
- 閉じるボタンは「現在のレンダーのみ非表示」に縮退 (リロードや再訪で再表示)
- ユニットテストを localStorage 前提から再レンダーで再表示する挙動に更新

スマホでは編集 UX が十分でない事実をユーザーが見落とすのを防ぐ意図。
編集 UX は Phase 2 で抜本対応する予定。

Refs #572

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
body の overflow-x を改変するアプローチ (前回のコミット) はメニュー
ツールチップを切ってしまい NG だった。

代替策として、CSS の position: fixed をやめて position: absolute +
window.visualViewport API による JS 位置決めに切り替え:

- バナーを document.body に Portal で飛ばす (これは継続)
- useLayoutEffect 内で visualViewport の resize / scroll を購読し、
  pageTop + height - bannerHeight を top に、pageLeft を left に、
  width を width に毎回適用
- ユーザーが page を縦スクロール / 横スクロールしても、バナーは常に
  視認可能な viewport の下端に追従する
- visualViewport が無い古い環境では window.innerHeight 等で代替

これにより:
- body / html / .app の overflow-x: hidden を撤回
- menu-bar の overflow-x: auto も撤回 (元々問題が無かった状態に戻る)
- メニューバーのツールチップなどの祖先要素クリップ問題が解消

Refs #572

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…isualViewport

これまでの試行錯誤を整理して、Phase 1 の最終形に着地:

1. playground/index.css の @media (min-width: 768px) で min-width/min-height
   を狭幅で外す変更を撤回。upstream のまま min-width: 1024px / min-height: 600px
   が常時適用されるように戻した。
   - これにより iPhone でもメニュー + ボディが一体で横スクロールする
     (upstream / develop と同じ挙動)
2. narrow-screen-warning は position: fixed + window.visualViewport で
   位置決め。fixed なので body の縦スクロール領域に影響しない。
   - top = vv.offsetTop + vv.height - bannerHeight
   - left = vv.offsetLeft
   - width = vv.width
   - resize / scroll を購読して visual viewport と同期
3. 撤回した Smalruby マーカー (responsive min-size override) を一覧から削除

これにより:
- メニュー + ボディが develop と同じく横スクロール (要望)
- 縦方向にスクロール領域が伸びない (絶対配置による拡張を撤回したため)
- バナーは visual viewport の下端に追従

Refs #572

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
iPhone 等の狭幅画面で、min-height: 600px と内部 GUI 要素の縦方向都合で
body が viewport より縦に伸び、ページ全体が縦スクロール可能になっていた。

@media (max-width: 767px) で html / body に overflow-y: clip を当てて
縦スクロールだけを抑止する。clip は overflow-x への副作用が無いので
横方向の min-width: 1024px 由来のスクロールはそのまま残る。

検証 (Playwright):
- htmlOverflowY = clip / bodyOverflowY = clip
- htmlOverflowX = visible / bodyOverflowX = visible
- window.scrollTo(0, 500) 後 scrollY = 0 (縦スクロール拒否)
- window.scrollTo(500, 0) 後 scrollX = 500 (横スクロール OK)

Refs #572

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@takaokouji takaokouji merged commit b4af8ba into develop Apr 29, 2026
9 checks passed
@takaokouji takaokouji deleted the fix/issue-572-responsive-phase-1 branch April 29, 2026 12:28
github-actions Bot pushed a commit that referenced this pull request Apr 29, 2026
…-responsive-phase-1

fix(gui): add narrow-screen warning + lift min-width below 768px (Phase 1 of #572)
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.

bug: iOS Safari など狭幅画面でスプライト/コスチューム追加が画面外になり操作不能 (responsive 対応)

1 participant