Skip to content

Add sticker types, page duplication, and UI improvements#6

Merged
kongyo2 merged 4 commits into
mainfrom
claude/upstream-changes-refactor-fbn1pv
Jul 25, 2026
Merged

Add sticker types, page duplication, and UI improvements#6
kongyo2 merged 4 commits into
mainfrom
claude/upstream-changes-refactor-fbn1pv

Conversation

@kongyo2

@kongyo2 kongyo2 commented Jul 25, 2026

Copy link
Copy Markdown
Owner

Summary

This release adds new sticker types, implements page/notebook duplication, improves accessibility, refactors theme constants, and enhances the overall UI with better visual feedback and component organization.

Key Changes

New Features

  • Sticker Types: Added 6 new sticker types (cloud, moon, crown, butterfly, paw, gem) to the existing 5, with complete SVG shape definitions and label support
  • Page Duplication: Implemented duplicatePage() function to clone pages with all their content (steps, stickers, shapes, etc.)
  • Notebook Duplication: Added duplicateNotebook() to duplicate entire notebooks with all pages
  • Menu System: Added modal menu to StickerTray with action rows for common operations
  • Progress Display: Added visual progress indicator to flowchart sections showing completed steps (e.g., "3/7")

UI & Accessibility Improvements

  • Accessibility: Added comprehensive accessibility labels, roles, and states throughout components (buttons, tabs, radio groups, progress bars)
  • Visual Feedback: Added pressed state styling to buttons and improved touch feedback with haptic support
  • Theme Refactoring: Consolidated scattered color literals and typography into centralized theme constants (palette, colors, text, space, radii, shadows)
  • Component Library: Created new UI components (IconButton, Chip, PanelTitle, GradientFill, WashiTape) for consistent styling
  • Chic Mode Styling: Added dedicated styling for "notestyle" (chic) mode with distinct button and tab appearances

Code Organization

  • Color Utilities: New color.ts module with functions for color manipulation (mix, lighten, darken, luminance detection)
  • Backup Format: Introduced backupFormat.ts with versioned backup envelope structure to support future format changes
  • Model Functions: Added moveStepInTree(), copyName(), duplicatePage(), duplicateNotebook(), and stepProgress() functions
  • Haptics: New haptics.ts module for safe haptic feedback (success, selection, impact)
  • Step Actions: Extracted move/delete controls into reusable StepActions component

Data Model Changes

  • Step Movement: Changed moveStep() to accept step ID instead of index for more reliable operations
  • Return Values: Step/shape addition functions now return the new element's ID for focus management
  • Branch Labels: Centralized default branch labels in constants
  • Notebook Defaults: Extracted default values (color, frame, rule style, paper color) to named constants

Bug Fixes & Refinements

  • Fixed notebook selection to use route ID directly, preventing "not found" flash on navigation
  • Improved page title handling and display
  • Better error handling in backup import/export
  • Removed deprecated findStepInTree() function in favor of direct tree operations

Testing

  • Added comprehensive tests for color utilities (color.test.ts)
  • Added backup format tests (backupFormat.test.ts)
  • Updated model tests to reflect new function signatures

Version & Dependencies

  • Bumped version to 0.3.0
  • Updated coverage configuration to include new utility modules

https://claude.ai/code/session_01VhmTi5pjG9aQVypwr6qSGN

## 上流(Web版)の変更の取り込み

- コピー機能: 手帳まるごと(表紙の📄)とページ単位(タブの📄)の複製。
  Web版のJSONディープコピーと違い、シール・テキスト・写真・工程すべてに
  新しいidを振り直し、矢印の参照も新しいシェイプidへ張り替える
- シール6種類を追加(くも・三日月・王冠・ちょうちょ・にくきゅう・宝石)→ 全11種類
- if分岐は画面幅によらず常に縦1カラム。RN版は元からこの挙動だが、
  意図としてコメントに残した(Web版の resize 対応textareaは、RNの
  multiline TextInputが自動で高さを合わせるため移植不要)

## html版とのインポート互換の打ち切り

- バックアップJSONを format/formatVersion を持つ独自の封筒形式に変更。
  封筒のないJSON(=Web版の書き出し)は「バックアップではない」として弾く
- rollbahn型名の読み替え、notestyleのnote→シェイプ移行、写真のimage別名
  といったWeb版専用の移行コードを削除

## バグ修正

- 編集画面を開いた1フレーム目に「手帳が見つかりませんでした」が出ていた。
  ルートのidから直接手帳を引き、遷移前にストア側も確定させる
- つなぎ線を動かす・伸ばす・回す手段が無く、updateArrow/resetArrowが
  到達不能だった。Transformableに載せて手動配置と↺の復帰を有効化
- ページ切替や手帳の開閉だけで「元に戻す」履歴が消えていた。履歴の比較から
  activeNotebookId/activePageIdを外し、手帳・ページの削除や取り込みも
  戻せるようにしたうえで、一覧画面にも取り消しボタンを置いた
- ReduceMotion.Never で端末の「視差効果を減らす」設定を無視していた。
  System に直し、きらめきと紙吹雪も設定を尊重する(Web版のprefers-reduced-motion相当)
- 分岐の中の工程を並べ替えられなかった(moveStepが添字ベースで最上位専用)。
  id基準のmoveStepInTreeにして木のどこでも並べ替え可能に
- シールが盤面のパディングぶんずれて配置されていた(Web版の.sticker-layerと
  同じ座標系になるよう、盤面いっぱいのレイヤーへ移動)
- 表紙の淡い色(はちみつ・グレー等)の上の白文字が読みづらかった → 輝度で判定
- 同じ日に2回書き出すとバックアップのファイル名が衝突していた(分まで入れる)
- 画像の共有ファイル名が "." や ".." になりうる穴を塞ぎ、日付を付ける
- react-native-svgのDefsのidが固定で、複数同時描画時に衝突しうる → useIdで一意化
- normalizePageのpaperColor既定値がnewPageと食い違っていた(#FBF7F2→#FFFFFF)

## UI・デザイン

- 表紙カードを「本」として作り直し(背表紙・マステで留めた名前ラベル・
  ページ数・押しやすいボタン帯)。作成パネルには表紙のライブプレビューを追加
- マスキングテープを唯一の主役の飾りとして表紙だけに使う(SVGで自作)
- ページタブを見出しインデックス風に。開いているタブに手帳の色の帯が乗る
- Web版のグラデーションボタンをSVGで再現
- 工程表の上に進み具合(3/7・満了で🎉)を表示
- ツールバーをシール帯+道具に整理し、読み込み・消去は「⋯」シートへ
- 追加した工程・条件・テキストに自動でフォーカスが移る(Web版と同じ)
- チェック・シール貼り・コピーに触覚フィードバック(未使用だったexpo-hapticsを活用)
- アイコンボタンのタップ判定を最低32dpに広げ、読み上げラベルを全面的に付与
- 破壊的な操作の文言を「戻せる」ことが分かる書き方に統一

## リファクタリング

- theme.tsを色・字・余白・角丸・影のトークン体系に拡張し、各コンポーネントに
  散っていた生の色リテラルとフォント指定をすべて集約
- 純粋ロジックを分離: color.ts(混色・輝度)、backupFormat.ts(封筒の組立と検証)、
  haptics.ts。いずれもカバレッジ100%の対象に追加
- CoverArt / StepActions / Gradient / WashiTape を抽出して重複を解消
- StickerShapeを1つのレジストリに集約(トレイ・盤面・紙吹雪・飾り枠が同じ定義を共有)
- 未使用だったfindStepInTree・fileStamp等のデッドコードと重複プロップを整理

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VhmTi5pjG9aQVypwr6qSGN
@coderabbitai

coderabbitai Bot commented Jul 25, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@kongyo2, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 25 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: QUIET

Plan: Pro Plus

Run ID: 163cc985-bbda-4e54-99ed-bfb782a1d701

📥 Commits

Reviewing files that changed from the base of the PR and between e0fc456 and a2c27c4.

📒 Files selected for processing (14)
  • src/components/board/BoardTabs.tsx
  • src/components/board/NoteControls.tsx
  • src/components/cover/CoverGrid.tsx
  • src/components/flowchart/FlowchartSection.tsx
  • src/components/flowchart/IfCard.tsx
  • src/components/freeform/ArrowLayer.tsx
  • src/components/freeform/FreeformCanvas.tsx
  • src/components/freeform/ShapeCard.tsx
  • src/components/transform/Transformable.tsx
  • src/components/ui/StickerShape.tsx
  • src/components/ui/Toast.tsx
  • src/lib/capture.ts
  • src/lib/model.test.ts
  • src/lib/types.ts
📝 Walkthrough

Walkthrough

Android 0.3.0 updates notebook creation and duplication, nested flowcharts, freeform editing, backups, stickers, accessibility, theming, reduced-motion behavior, testing utilities, and release metadata.

Changes

Android 0.3.0

Layer / File(s) Summary
Shared contracts, model helpers, and notebook state
src/lib/types.ts, src/lib/model.ts, src/state/notebooks.ts, src/state/ui.ts
Adds shared limits/defaults, recursive step operations, duplication helpers, progress calculation, ID-returning actions, route selectors, focus state, and revised undo history.
Backup envelope and validation
src/lib/backupFormat.ts, src/lib/backup.ts, src/state/backup.ts, src/lib/*test.ts
Adds versioned JSON envelopes, normalization and rejection reasons, updated import confirmation, and tests for backup parsing and state normalization.
Notebook editor and board interactions
src/app/notebook/[id].tsx, src/components/board/*, src/components/freeform/*, src/components/transform/*
Updates route-based notebook selection, page actions, dynamic board sizing, transformable stickers/arrows/photos/shapes, haptics, and accessibility labels.
Flowchart progress and nested branch controls
src/components/flowchart/*
Adds progress indicators, connectors, recursive branch rendering, shared step actions, focus handling, and reduced-motion confetti behavior.
Notebook covers and controls
src/components/cover/*, src/components/board/BoardTabs.tsx, src/components/board/StickerTray.tsx
Adds cover artwork and previews, notebook duplicate actions, active tab controls, themed tray menus, and accessibility metadata.
Shared UI, theming, and motion
src/lib/theme.ts, src/components/ui/*
Centralizes color, typography, spacing, radius, and shadow tokens; adds unique SVG IDs, gradient/tape components, sticker registry support, and reduced-motion sparkle rendering.
Release metadata and documentation
README.md, app.json, package.json, src/app/_layout.tsx, vitest.config.ts
Documents the 0.3.0 backup format and development commands, bumps release identifiers, centralizes autosave timing, follows system motion settings, and expands coverage targets.

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

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant CoverScreen
  participant NotebookStore
  participant NotebookEditor
  participant BackupFlow

  User->>CoverScreen: create, duplicate, delete, or open notebook
  CoverScreen->>NotebookStore: execute notebook action
  NotebookStore-->>CoverScreen: return ID, success, or undo state
  CoverScreen->>NotebookEditor: navigate with notebook ID
  User->>NotebookEditor: edit page or request backup
  NotebookEditor->>NotebookStore: commit page changes
  NotebookEditor->>BackupFlow: export or import JSON
  BackupFlow->>NotebookStore: apply validated state
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately reflects the main changes: new sticker types, duplication features, and UI improvements.
Description check ✅ Passed The description is clearly related to the changeset and summarizes the implemented features and refactors.
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.

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.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e0fc4566ab

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

<View style={styles.body}>{children}</View>
<View
style={styles.body}
accessible={label !== undefined}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Keep editable text outside the accessible wrapper

When ShapeCard supplies a label, this accessible view groups its descendant TextInput into one generic accessibility element. On Android with TalkBack enabled, users can no longer focus the text field independently as an editable control, blocking freeform-text editing; only non-interactive sticker, photo, and arrow bodies should be grouped this way.

Useful? React with 👍 / 👎.

Comment thread src/components/freeform/ArrowLayer.tsx Outdated
selected={selected}
bodyDraggable
handleTint={chic.handle}
boundsWidth={boundsWidth}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Do not clamp rotated arrows to the canvas width

Passing boundsWidth makes Transformable clamp the arrow's length to the horizontal canvas width, even though w represents the arrow's rotated Euclidean length. For shapes separated vertically or diagonally by more than the canvas width, the previously endpoint-to-endpoint arrow is rendered shortened and no longer connects the two shapes; arrow positioning needs rotation-aware bounds or should avoid this width clamp.

Useful? React with 👍 / 👎.

Comment thread src/lib/backupFormat.ts
export function parseBackup(raw: unknown): BackupParseResult {
if (typeof raw !== "object" || raw === null || Array.isArray(raw)) return { ok: false, reason: "notBackup" };
const envelope = raw as Partial<BackupEnvelope>;
if (envelope.format !== BACKUP_FORMAT) return { ok: false, reason: "notBackup" };

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Accept backups from the previous Android release

The immediately preceding Android version's exportBackup serialized a bare AppState, without this new envelope—the same representation now described as Web-only. Consequently, every backup created by Android 0.2.1 is rejected here as notBackup after upgrading to 0.3.0, preventing users from restoring their existing recovery files; recognize and normalize the legacy top-level { activeNotebookId, notebooks } form.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

指摘の事実関係は正しく、v0.1.0〜v0.2.1 のAPKも実際にリリース済みなので、0.2.1 で書き出したバックアップが 0.3.0 で読めなくなるのはその通りです。そのうえで、今回は**現状のまま(封筒のないJSONは受け付けない)**で進めます。

理由は、0.2.1 の exportBackup が書き出す { activeNotebookId, notebooks } と Web版 (index.html) の書き出しが構造的に完全に同一で、両者を区別する手段が無いためです。旧形式を受け入れると、このPRの要件である「Web版とのインポート互換の打ち切り」が事実上撤回されます。二者択一になるため作者に確認し、互換打ち切りを優先する判断となりました。

移行手段は README に記載してあります(0.2.x で復元 → 0.3.0 で書き出し直す)。


Generated by Claude Code

Comment thread src/app/notebook/[id].tsx
addShape(p.x, p.y);
const newId = addShape(p.x, p.y);
select(newId);
useUi.getState().setFocus(newId);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Consume the focus request for new text shapes

Pressing +テキスト stores the new shape ID in focusId, but ShapeCard never reads that state or applies autoFocus to its TextInput (only the flowchart components consume it). The new card is selected but the keyboard does not open and the user must tap the input again, so the focus-management path introduced here does not work for text shapes.

Useful? React with 👍 / 👎.

minW={ARROW_MIN_LENGTH}
maxW={ARROW_MAX_LENGTH}
selected={selected}
bodyDraggable

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Keep manually moved arrows within the scrollable canvas

Enabling body dragging allows an arrow to acquire an arbitrarily large y coordinate because Transformable enforces only a lower bound. FreeformCanvas calculates its height from shapes, photos, and stickers but not manual arrows, and absolute children do not enlarge layout, so dragging a line below the last content can place it beyond the ScrollView's reachable extent and leave no way to select, reset, or delete it; include manual arrows in the canvas extent or cap their vertical movement.

Useful? React with 👍 / 👎.

- Transformable: 中身をひとかたまりの読み上げ要素にまとめる挙動を
  bodyAccessible で切れるようにし、編集できる入力欄を持つテキストカードでは
  無効化する。TalkBack から入力欄に降りられなくなっていた
- Transformable: 位置と幅をキャンバス内へ丸めるかを bounded で切れるように
  し、矢印では無効化する。回転した矢印の「箱の左上」は画面上の位置と一致
  しないため、紙の幅で丸めると離れた図形をつなぐ長い線が縮んで届かなくなっていた
- FreeformCanvas: 紙の高さの計算に手動配置の矢印を含める。図形から離れた
  位置へ動かした線が紙の外に出て、選択も削除もできなくなることがあった
- ShapeCard: 「+テキスト」で置いたカードにフォーカスが移っていなかった
  (focusId を工程側しか読んでいなかった)。選択が乗ってから入力欄を focus する

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VhmTi5pjG9aQVypwr6qSGN

@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: 5

Note

Quiet mode is enabled, so only the most important comments were posted inline. Other review comments are grouped below.

🟡 Other comments (2)
src/app/notebook/[id].tsx-188-192 (1)

188-192: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Silent no-op when duplication is rejected.

Every other page action gives feedback (onDeletePage toasts on the last-page guard), but a falsy duplicatePage result here returns with no user-visible signal.

💡 Add a failure toast
   const onDuplicatePage = (pageId: string) => {
-    if (!duplicatePage(pageId)) return;
+    if (!duplicatePage(pageId)) {
+      showToast("⚠️ ページをコピーできませんでした");
+      return;
+    }
     tapFeedback();
     showToast("ページをコピーしたよ📄✨");
   };
src/components/board/BoardTabs.tsx-151-158 (1)

151-158: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

borderRadius: 0 won't flatten the tab corners.

styles.tab sets the four individual corner props (borderTopLeftRadius etc.), and in React Native the specific corner properties win over borderRadius irrespective of style-array order. Chic tabs will keep the 14/4 rounding.

🎨 Proposed fix
   tabChic: {
     backgroundColor: "transparent",
-    borderRadius: 0,
+    borderTopLeftRadius: 0,
+    borderTopRightRadius: 0,
+    borderBottomLeftRadius: 0,
+    borderBottomRightRadius: 0,
     borderWidth: 0,
🧹 Nitpick comments (5)
src/lib/model.test.ts (1)

680-690: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add a photo-id-regenerated assertion for full duplication coverage.

This test checks id regeneration for steps, stickers, and shapes, but not for photos, even though duplicatePage regenerates photo ids too (photos: page.photos.map((p) => ({ ...p, id: newId() }))). Only dataUrl retention is checked here.

♻️ Suggested addition
     expect(copy.photos[0]?.dataUrl).toBe("data:image/png;base64,AAAA");
+    expect(copy.photos[0]?.id).not.toBe("ph1");
src/components/ui/StickerShape.tsx (1)

21-162: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Sticker default colors duplicate palette tokens instead of importing them.

Several c1/c2 defaults here are literal copies of palette entries in src/lib/theme.ts (e.g. "#F4D58D" = palette.gold, "#E8B4BC" = palette.rose, "#C9B6E4" = palette.lavender, "#A8E6CF" = palette.mint, "#FFFFFF" = palette.white). The crown (Line 114-115) and butterfly (Line 132) draws also hardcode extra stroke colors ("#FFFFFF", "#7A6A90") that never go through c1/c2 at all. This duplicates the exact palette this PR introduces to centralize color literals, so a future palette retune won't propagate here.

♻️ Example fix (import and reuse palette tokens)
+import { palette } from "`@/lib/theme`";
+
 const STICKERS: Record<StickerType, StickerDef> = {
   star: {
     label: "星",
-    c1: "`#F4D58D`",
-    c2: "`#FFFFFF`",
+    c1: palette.gold,
+    c2: palette.white,
     ...
src/components/flowchart/FlowchartSection.tsx (1)

22-37: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add accessibilityValue to the progress bar.

The progressbar role currently relies solely on the text label. Pairing it with accessibilityValue={{ min: 0, max: total, now: done }} gives assistive tech a structured, standard way to report progress instead of parsing free text.

♻️ Proposed addition
     <View
       style={styles.progress}
       accessibilityRole="progressbar"
       accessibilityLabel={`${total}工程のうち${done}つ完了`}
+      accessibilityValue={{ min: 0, max: total, now: done }}
     >
src/components/flowchart/IfCard.tsx (1)

120-161: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Branch step completion misses haptic/confetti feedback.

BranchStepRow's onPress={() => toggleStep(branch.id)} toggles completion but never calls successFeedback() or renders <Confetti/>, unlike StepCard's onCheck, which fires both on transition to done. This creates an inconsistent celebration experience depending on whether a step lives at the top level or inside an if-branch.

♻️ Proposed fix to mirror StepCard's onCheck behavior
+import { successFeedback } from "`@/lib/haptics`";
+import { Confetti } from "./Confetti";
+import { useState } from "react";
 ...
 function BranchStepRow({ branch, position }: { branch: NormalStep; position: Position }) {
   const setStepText = useNotebooks((s) => s.setStepText);
   const toggleStep = useNotebooks((s) => s.toggleStep);
   const deleteStep = useNotebooks((s) => s.deleteStep);
   const focusId = useUi((s) => s.focusId);
   const setFocus = useUi((s) => s.setFocus);
+  const [burst, setBurst] = useState(0);
+
+  const onCheck = () => {
+    const nowDone = toggleStep(branch.id);
+    if (nowDone) {
+      setBurst((b) => b + 1);
+      successFeedback();
+    }
+  };

   return (
     <View style={styles.branchStep}>
       <Pressable
         style={[styles.bcheck, branch.done && styles.bcheckDone]}
-        onPress={() => toggleStep(branch.id)}
+        onPress={onCheck}
         hitSlop={8}
         ...
       >
         ...
       </Pressable>
       ...
+      {burst > 0 ? <Confetti key={burst} /> : null}
     </View>
   );
 }
src/components/board/NoteControls.tsx (1)

70-79: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Use a non-color indicator for the selected paper-color swatch.

swatchActive only changes chic.border (#DDDDDD) to chic.rule (#3A3A3A), so selection can be missed by users who cannot rely on a color-only state. Add a visible cue such as a thicker border, selected ring, or check mark in the selected style.


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: QUIET

Plan: Pro Plus

Run ID: 4e32a87c-f968-4513-a94f-5f490ddcf700

📥 Commits

Reviewing files that changed from the base of the PR and between f9cdea2 and e0fc456.

📒 Files selected for processing (52)
  • README.md
  • app.json
  • package.json
  • src/app/_layout.tsx
  • src/app/index.tsx
  • src/app/notebook/[id].tsx
  • src/components/board/BoardFrame.tsx
  • src/components/board/BoardTabs.tsx
  • src/components/board/FrameSelect.tsx
  • src/components/board/NoteControls.tsx
  • src/components/board/PaperBackground.tsx
  • src/components/board/StickerItem.tsx
  • src/components/board/StickerTray.tsx
  • src/components/cover/CoverArt.tsx
  • src/components/cover/CoverGrid.tsx
  • src/components/cover/CreatePanel.tsx
  • src/components/flowchart/Confetti.tsx
  • src/components/flowchart/FlowchartSection.tsx
  • src/components/flowchart/IfCard.tsx
  • src/components/flowchart/StepActions.tsx
  • src/components/flowchart/StepCard.tsx
  • src/components/freeform/ArrowLayer.tsx
  • src/components/freeform/FreeformCanvas.tsx
  • src/components/freeform/PhotoCard.tsx
  • src/components/freeform/ShapeCard.tsx
  • src/components/notebook/NotebookSection.tsx
  • src/components/transform/Transformable.tsx
  • src/components/ui/Background.tsx
  • src/components/ui/Gradient.tsx
  • src/components/ui/PromptModal.tsx
  • src/components/ui/SparkleLayer.tsx
  • src/components/ui/StickerShape.tsx
  • src/components/ui/Toast.tsx
  • src/components/ui/WashiTape.tsx
  • src/components/ui/kit.tsx
  • src/lib/backup.ts
  • src/lib/backupFormat.test.ts
  • src/lib/backupFormat.ts
  • src/lib/capture.ts
  • src/lib/color.test.ts
  • src/lib/color.ts
  • src/lib/format.test.ts
  • src/lib/format.ts
  • src/lib/haptics.ts
  • src/lib/model.test.ts
  • src/lib/model.ts
  • src/lib/theme.ts
  • src/lib/types.ts
  • src/state/backup.ts
  • src/state/notebooks.ts
  • src/state/ui.ts
  • vitest.config.ts

Comment thread src/components/board/BoardTabs.tsx Outdated
Comment thread src/components/freeform/FreeformCanvas.tsx Outdated
Comment thread src/components/transform/Transformable.tsx
Comment thread src/components/ui/Toast.tsx
Comment thread src/lib/capture.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4a46789dc9

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

handleTint={chic.handle}
// 矢印は回転させて使うので、箱の左上はキャンバス上の位置と一致しない。
// ここを紙の幅で丸めると、離れた図形をつなぐ長い線が縮んで届かなくなる。
bounded={false}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Keep dragged arrows within a recoverable area

When a selected arrow is dragged far enough toward the top or either horizontal edge, bounded={false} permits its center—and therefore the entire visible rotated line—to leave the canvas. The resulting coordinates are persisted by updateArrow, while the canvas provides neither upward nor horizontal scrolling, so the arrow can no longer be selected to reset or delete it; preserve the rotation-aware sizing fix while constraining the arrow's visible center or retaining a reachable portion.

Useful? React with 👍 / 👎.

- Transformable: 「↺ 自動の位置に戻す」ボタンが回転つまみと同じ左上角に
  重なり、手動配置した矢印を回せなくなっていた。空いている左下へ移動
- ArrowLayer: bounded={false} にしたことで、矢印を紙の外まで動かせて
  しまい、選び直しも削除もできなくなる余地が残っていた。箱の左上ではなく
  「掴める中心」を紙の中に丸める(回転した線が紙からはみ出すのは正常なので、
  そこは丸めない)
- BoardTabs: タブの外枠を押せない容れ物にして、ページ切り替えとコピー・削除
  を兄弟に並べた。押せる要素の入れ子は TalkBack が外側だけをひとかたまりで
  拾い、中のボタンに降りられなくなるため
- BoardTabs: ノート式の平らなタブに borderRadius:0 が効いていなかった
  (React Native では個別の角指定が shorthand より優先される)
- Toast: 読み上げ領域ごと出し入れしていたため、知らせが読み上げられない
  ことがあった。入れ物は出したままにして中身だけ差し替える
- capture: 同じページを同じ日に2回保存すると同名になり、前回の共有がまだ
  開いているかもしれないファイルを消していた。分まで入れたうえで、既存
  ファイルには触れず一時ファイルをそのまま共有する
- NoteControls: 用紙色の選択が枠の色だけの違いだったので、チェックを重ねて
  形でも分かるようにした
- IfCard: 分岐の中の工程にチェックを付けたときの手ごたえが無かった
- FlowchartSection: 進み具合バーに accessibilityValue を付与
- 未計測テキストカードの高さの見積もりが2か所で食い違っていた(120と44)
  ので UNMEASURED_SHAPE_HEIGHT に集約
- StickerShape: シールの既定色をパレットのトークン参照に置き換え

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VhmTi5pjG9aQVypwr6qSGN

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 993a0f4ddf

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/components/cover/CoverGrid.tsx Outdated
Comment on lines +30 to +34
<Pressable
style={({ pressed }) => [styles.card, pressed && styles.cardPressed]}
onPress={onOpen}
accessibilityRole="button"
accessibilityLabel={`${name}を開く`}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Keep cover actions outside the accessible opener

With TalkBack enabled, this outer Pressable becomes one accessibility element labeled “...を開く” and groups the nested IconButton controls, so users cannot focus the rename, copy, or delete actions independently. Use a non-accessible card wrapper and make the opener and action buttons siblings, as BoardTabs does for the same Android behavior.

Useful? React with 👍 / 👎.

Comment thread src/components/cover/CoverGrid.tsx Outdated
const name = notebookDisplayName(notebook);

return (
<Animated.View style={styles.cell} entering={FadeInDown.delay(index * 45).duration(260)}>

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Cap the staggered cover animation delay

When a backup or long-lived installation contains many notebooks, multiplying every index by 45 ms makes later covers—and the add card, which uses the total notebook count—remain in their delayed entering state for several seconds (100 notebooks means about 4.5 seconds). Because notebook count is unbounded, cap the stagger index so large collections become usable immediately.

Useful? React with 👍 / 👎.

- CoverGrid: カードの外枠を押せない容れ物にして、「開く」と名前の変更・
  コピー・削除を兄弟に並べた。押せる要素の入れ子は TalkBack が外側だけを
  ひとかたまりで拾い、中のボタンに降りられなくなるため(BoardTabs で直した
  のと同じ構造の見落とし)
- CoverGrid: 表紙が順に浮かび上がる演出のずらし段数に上限を設けた。冊数に
  比例して遅らせていたため、冊数が多いと最後のカードと「新しい手帳」タイル
  が数秒間ずっと出てこなかった(100冊で約4.5秒)

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VhmTi5pjG9aQVypwr6qSGN
@kongyo2
kongyo2 merged commit 937b02e into main Jul 25, 2026
5 checks passed
@kongyo2
kongyo2 deleted the claude/upstream-changes-refactor-fbn1pv branch July 25, 2026 08:30
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.

2 participants