From swift-design-system
UIの視覚的差分を検出・比較する。デザイン変更前後の比較、リファレンスとの差分確認時に使用。「デザイン比較」「UI差分」「design diff」「design compare」「ビフォーアフター」「見た目の違い」などのキーワードで自動適用。
npx claudepluginhub no-problem-dev/claude-code-plugins --plugin swift-design-systemThis skill uses the workspace's default tool permissions.
UI の変更前後を比較し、視覚的な差分を検出・分析する。
Guides Next.js Cache Components and Partial Prerendering (PPR) with cacheComponents enabled. Implements 'use cache', cacheLife(), cacheTag(), revalidateTag(), static/dynamic optimization, and cache debugging.
Guides building MCP servers enabling LLMs to interact with external services via tools. Covers best practices, TypeScript/Node (MCP SDK), Python (FastMCP).
Generates original PNG/PDF visual art via design philosophy manifestos for posters, graphics, and static designs on user request.
UI の変更前後を比較し、視覚的な差分を検出・分析する。
3つの手法を組み合わせて使用する。
swift-snapshot-testing を使用してスナップショットの差分を検出する。
仕組み:
record: true でリファレンス画像を保存record: false(デフォルト)で現在の状態をリファレンスと比較差分画像の出力先:
Tests/
__Snapshots__/ # リファレンス画像
TestClassName/
testMethodName.1.png
Failures/ # 差分画像(テスト失敗時に生成)
testMethodName.1.png
2つの PNG 画像を Read ツールで読み込み、視覚的に比較する。
使用場面:
View のソースコードを比較し、トークンの変更を特定する。
使用場面:
import XCTest
import SnapshotTesting
@testable import YourApp
final class MyViewSnapshotTests: XCTestCase {
func testMyView() {
let view = MyView()
.frame(width: 375)
.theme(ThemeProvider())
// リファレンス記録(初回のみ record: true)
isRecording = true
assertSnapshot(of: view, as: .image)
}
}
テスト実行:
xcodebuild test \
-scheme YourScheme \
-destination 'platform=iOS Simulator,name=iPhone 16' \
-only-testing:YourTests/MyViewSnapshotTests/testMyView
View のソースコードを修正する。
// record を false に戻す(またはデフォルト)
func testMyView() {
let view = MyView()
.frame(width: 375)
.theme(ThemeProvider())
// リファレンスと比較(差異があればテスト失敗)
assertSnapshot(of: view, as: .image)
}
テスト実行:
xcodebuild test \
-scheme YourScheme \
-destination 'platform=iOS Simulator,name=iPhone 16' \
-only-testing:YourTests/MyViewSnapshotTests/testMyView
テストが失敗した場合: 差分画像が Failures/ ディレクトリに生成される。
Read ツールで以下の画像を読み込んで分析する:
__Snapshots__/TestClassName/testMethodName.1.pngFailures/testMethodName.1.png(差分を含む)差分の内容に基づいて:
// 一時的に record: true に戻してリファレンスを更新
isRecording = true
assertSnapshot(of: view, as: .image)
テスト実行後、isRecording = true を削除してコミット。
# Design Diff レポート
**対象**: `MyView.swift`
**比較**: リファレンス vs 現在
## 変更サマリー
| 項目 | Before | After | 影響 |
|------|--------|-------|------|
| 背景色 | surface | primaryContainer | 視覚的に大きい変化 |
| パディング | spacing.md (12pt) | spacing.lg (16pt) | レイアウトに影響 |
| 角丸 | radius.md | radius.lg | 軽微な変化 |
## 視覚的差分
- **変化あり**: 背景色がより強調された色に変更
- **変化あり**: 内部余白が広がりコンテンツが収縮
- **変化なし**: テキスト、アイコン、アニメーション
## Design System 準拠性
変更後の状態が Design System に準拠しているか:
- ✅ すべてのカラーが ColorPalette 経由
- ✅ すべてのスペーシングが SpacingScale 経由
- ⚠️ ダークモードでの確認が必要
差分検出後、変更が Design System 準拠性を改善したか悪化させたかを確認する:
design-audit を実行(結果を記録)design-diff で視覚的差分を確認design-audit を再実行final class MyViewSnapshotTests: XCTestCase {
// デフォルトテーマ・ライトモード
func testDefault() {
let view = MyView()
.frame(width: 375)
.theme(ThemeProvider())
assertSnapshot(of: view, as: .image)
}
// ダークモード
func testDarkMode() {
let view = MyView()
.frame(width: 375)
.theme(ThemeProvider(initialMode: .dark))
assertSnapshot(of: view, as: .image)
}
// Large Text
func testLargeText() {
let view = MyView()
.frame(width: 375)
.theme(ThemeProvider())
.environment(\.sizeCategory, .accessibilityExtraLarge)
assertSnapshot(of: view, as: .image)
}
// 別テーマ
func testOceanTheme() {
let view = MyView()
.frame(width: 375)
.theme(ThemeProvider(initialTheme: OceanTheme()))
assertSnapshot(of: view, as: .image)
}
}