iPhone Duo (fase 1): navegación adaptativa por size class y layouts regular×regular

- ContentView: un único TabView (sidebarAdaptable en iOS 18+) para todas las
  size classes; desaparece el cambio de jerarquía iPhone/iPad, así abrir o
  cerrar el Duo conserva el estado de cada pestaña. @SceneStorage de la tab.
- Fuentes y Diario: NavigationSplitView (lista + detalle a la vez en ancho
  regular, stack colapsable en compacto) con selección nativa de List.
- Dashboard: Quick Update como .inspector (panel lateral junto a los gráficos
  en regular, sheet en compacto).
- Gráficos: chartHeightScale (+35% de alto en regular) vía chartFrame(height:),
  sin ignoresSafeArea en contenido interactivo.
- Liquid Glass (glassEffect) en las etiquetas flotantes del Diario en iOS 26+.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01F1u4K16xy7eQVtgsYNZ9Vn
This commit is contained in:
alexandrev-tibco
2026-09-16 11:44:50 +02:00
parent a8a9ad64f3
commit 680255f69d
17 changed files with 485 additions and 547 deletions
@@ -19,7 +19,7 @@ struct AllocationSimulatorView: View {
}
.padding()
.background(Color(.systemBackground))
.cornerRadius(AppConstants.UI.cornerRadius)
.clipShape(RoundedRectangle(cornerRadius: AppConstants.UI.cornerRadius))
.shadow(color: .black.opacity(0.05), radius: 8, y: 2)
}
@@ -29,13 +29,13 @@ struct AllocationSimulatorView: View {
VStack(spacing: 12) {
Image(systemName: "slider.horizontal.3")
.font(.system(size: 36))
.foregroundColor(.secondary)
.foregroundStyle(.secondary)
Text("No sources available")
.font(.subheadline)
.foregroundColor(.secondary)
.foregroundStyle(.secondary)
}
.frame(maxWidth: .infinity)
.frame(height: 300)
.chartFrame(height: 300)
}
// MARK: - Allocation Card
@@ -56,7 +56,7 @@ struct AllocationSimulatorView: View {
}
.padding(12)
.background(Color(.systemGray6))
.cornerRadius(10)
.clipShape(RoundedRectangle(cornerRadius: 10))
}
private var totalAllocationBadge: some View {
@@ -67,8 +67,8 @@ struct AllocationSimulatorView: View {
.padding(.horizontal, 8)
.padding(.vertical, 3)
.background(isNear100 ? Color.green.opacity(0.15) : Color.orange.opacity(0.15))
.foregroundColor(isNear100 ? .green : .orange)
.cornerRadius(8)
.foregroundStyle(isNear100 ? .green : .orange)
.clipShape(RoundedRectangle(cornerRadius: 8))
}
private var resetButton: some View {
@@ -87,7 +87,7 @@ struct AllocationSimulatorView: View {
} label: {
Image(systemName: "arrow.counterclockwise")
.font(.caption)
.foregroundColor(.secondary)
.foregroundStyle(.secondary)
}
.buttonStyle(.plain)
}
@@ -104,11 +104,11 @@ struct AllocationSimulatorView: View {
Spacer()
Text(String(format: "%.0f%%", source.simulatedPct))
.font(.caption.weight(.semibold))
.foregroundColor(.primary)
.foregroundStyle(.primary)
.frame(width: 36, alignment: .trailing)
Text(String(format: "(%.0f%%)", source.currentPct))
.font(.caption2)
.foregroundColor(.secondary)
.foregroundStyle(.secondary)
}
Slider(
@@ -142,8 +142,8 @@ struct AllocationSimulatorView: View {
if viewModel.simulatorActualData.isEmpty && viewModel.simulatorData.isEmpty {
Text("Not enough data to simulate.")
.font(.subheadline)
.foregroundColor(.secondary)
.frame(height: 220)
.foregroundStyle(.secondary)
.chartFrame(height: 220)
} else {
simulationChart
chartLegend
@@ -194,7 +194,7 @@ struct AllocationSimulatorView: View {
.foregroundStyle(Color.secondary.opacity(0.15))
}
}
.frame(height: 220)
.chartFrame(height: 220)
.chartDrawingGroup(disabledForExport: chartImageExport)
}
@@ -224,7 +224,7 @@ struct AllocationSimulatorView: View {
}
Text(label)
.font(.caption)
.foregroundColor(.secondary)
.foregroundStyle(.secondary)
}
}