Skip to content

feat(ui): add frame aspect ratio, orientation, and alignment controls#20

Merged
amemya merged 1 commit into
mainfrom
feat/issue-8-frame-aspect-ratio
May 22, 2026
Merged

feat(ui): add frame aspect ratio, orientation, and alignment controls#20
amemya merged 1 commit into
mainfrom
feat/issue-8-frame-aspect-ratio

Conversation

@amemya
Copy link
Copy Markdown
Owner

@amemya amemya commented May 22, 2026

Resolved #8

@amemya amemya requested a review from Copilot May 22, 2026 00:16
@amemya amemya self-assigned this May 22, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 22, 2026

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 37dc6725-09f9-4215-8e93-ac921d88ba26

📥 Commits

Reviewing files that changed from the base of the PR and between 0d755e5 and c59903a.

📒 Files selected for processing (2)
  • frontend/src/App.css
  • frontend/src/App.tsx

📝 Walkthrough

Summary by CodeRabbit

リリースノート

  • 新機能

    • フレーム設定機能を追加。アスペクト比プリセット、カスタム比率、向き、縦位置配置をサイドバーから選択可能に。
    • セグメントコントロール UI を新規追加。
  • スタイル改善

    • 選択メニューの外観を入力フィールドと統一。カスタムドロップダウン矢印を実装。

Walkthrough

フレーム設定機能をサポートするため、キャンバス描画ロジックをアスペクト比・向き・縦位置に対応させるよう拡張。フォーム・セグメントコントロール用CSS基盤を追加し、stateとUIコンポーネントを新規実装。

Changes

Frame Settings and Canvas Orientation

Layer / File(s) Summary
Form Controls and Segmented Control CSS
frontend/src/App.css
.input-groupinputselect を共通スタイルで統一し、select に右側カスタムSVG矢印を追加。セグメントコントロール(.segmented-control.segment、アクティブ/ホバー状態、disabled 状態)の完全なスタイルセットを新規定義。
Frame Settings State and Image Orientation
frontend/src/App.tsx
アスペクト比プリセット(square/instagram/custom)、カスタム幅高さ、orientation(landscape/portrait)、縦位置アラインメント(top/center)用のstate変数を追加。画像選択時に画像の縦横比から orientation を初期推定。
Canvas Drawing with Orientation and Alignment
frontend/src/App.tsx
drawCanvasuseCallback 化し、フレーム設定から実際のキャンバス寸法と画像配置座標(drawX/drawY)を計算。キャンバス背景描画、画像配置、テキスト座標、区切り線位置をこれらの計算値に基づいて更新。useEffect依存配列をフレーム設定に合わせて調整。
Frame Settings Sidebar UI
frontend/src/App.tsx
サイドバーに「Frame Settings」セクションを新設。アスペクト比プリセット選択、カスタム入力(custom時のみ表示)、Orientation セグメント(1:1では無効化)、Vertical Alignment セグメント(top/center選択)を実装。

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • amemya/ExifFrame#11: PR #11frontend/src/App.css のフォームコントロール全体を刷新しており、Main PR のフォーム共通スタイル(input/select)との重複がある可能性がある。
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed タイトルはPRの主要な変更内容(フレームのアスペクト比、向き、垂直配置コントロール機能の追加)を正確に記述しており、変更セットの中心的なテーマを明確に反映しています。
Description check ✅ Passed 説明文は「Resolved #8」と関連するissueを明記しており、変更内容と関連がある必要最小限の説明として機能しています。
Linked Issues check ✅ Passed Issue #8はハードコードされたアスペクト比に対応でき、ユーザーが自由に選択できるようにすることを要求しており、本PRはアスペクト比プリセット・カスタム値・向き・垂直配置コントロールを実装してこの要件を完全に満たしています。
Out of Scope Changes check ✅ Passed すべての変更がフレーム設定(アスペクト比、向き、垂直配置)の実装に直結しており、Issue #8の要件内に収まっています。select要素のスタイリング(App.css)はUI実装の必要な部分です。

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ 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/issue-8-frame-aspect-ratio

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 and usage tips.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR resolves issue #8 by removing the hard-coded output frame ratio and adding UI controls so users can choose the frame aspect ratio, orientation, and vertical alignment—improving rendering for portrait photos.

Changes:

  • Added frame settings state (aspect ratio preset/custom, orientation, alignment) and integrated them into the canvas layout calculation.
  • Updated the canvas drawing logic to compute final canvas dimensions based on a chosen target ratio and to reposition the image/text accordingly.
  • Extended sidebar UI and styles to support <select> inputs and segmented controls for the new settings.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
frontend/src/App.tsx Adds frame settings UI/state and updates drawCanvas to support configurable aspect ratios, orientation flipping, and vertical alignment.
frontend/src/App.css Styles the new aspect ratio <select> and segmented controls used by the frame settings UI.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread frontend/src/App.tsx
Comment on lines +155 to +185
let targetRatio = 4300 / 3618;
if (aspectRatioPreset === "custom") {
if (customRatioW > 0 && customRatioH > 0) {
targetRatio = customRatioW / customRatioH;
} else {
targetRatio = img.width / img.height;
}
} else {
const [w, h] = aspectRatioPreset.split(':').map(Number);
if (w && h) targetRatio = w / h;
}

// Apply orientation flip
if (orientation === "portrait" && targetRatio > 1) {
targetRatio = 1 / targetRatio;
} else if (orientation === "landscape" && targetRatio < 1) {
targetRatio = 1 / targetRatio;
}

const minCanvasWidth = img.width + (minFramePadding * 2);
const minCanvasHeight = img.height + minFramePadding + minBottomSpace;

// 全体の仕上がりを 4300 : 3618 の比率に強制する
const targetRatio = 4300 / 3618;
// まず幅を基準に高さを計算
let finalCanvasWidth = minCanvasWidth;
let finalCanvasHeight = Math.floor(finalCanvasWidth / targetRatio);

if (finalCanvasHeight < minCanvasHeight) {
// 高さが足りない場合は、最小の高さを基準にして幅を拡張
finalCanvasHeight = minCanvasHeight;
finalCanvasWidth = Math.floor(finalCanvasHeight * targetRatio);
}
Comment thread frontend/src/App.tsx
Comment on lines +443 to +480
<label>Orientation</label>
<div className={`segmented-control ${aspectRatioPreset === '1:1' ? 'disabled' : ''}`}>
<button
className={`segment ${orientation === 'landscape' ? 'active' : ''}`}
onClick={() => setOrientation('landscape')}
disabled={aspectRatioPreset === '1:1'}
>
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><rect x="3" y="5" width="18" height="14" rx="2" ry="2"></rect></svg>
Landscape
</button>
<button
className={`segment ${orientation === 'portrait' ? 'active' : ''}`}
onClick={() => setOrientation('portrait')}
disabled={aspectRatioPreset === '1:1'}
>
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><rect x="5" y="3" width="14" height="18" rx="2" ry="2"></rect></svg>
Portrait
</button>
</div>
</div>
<div className="input-group">
<label>Vertical Alignment</label>
<div className="segmented-control">
<button
className={`segment ${alignment === 'top' ? 'active' : ''}`}
onClick={() => setAlignment('top')}
>
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><line x1="4" y1="4" x2="20" y2="4"></line><rect x="8" y="8" width="8" height="8" rx="1" ry="1"></rect></svg>
Top
</button>
<button
className={`segment ${alignment === 'center' ? 'active' : ''}`}
onClick={() => setAlignment('center')}
>
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><line x1="4" y1="12" x2="20" y2="12"></line><rect x="8" y="8" width="8" height="8" rx="1" ry="1"></rect></svg>
Center
</button>
</div>
@amemya amemya merged commit 2f94261 into main May 22, 2026
2 checks passed
@amemya amemya deleted the feat/issue-8-frame-aspect-ratio branch May 22, 2026 00:27
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