Signed-off-by: Matt Bruce <mbrucedogs@gmail.com>
This commit is contained in:
parent
90366720c0
commit
1d9100c018
@ -14,6 +14,15 @@ struct AndromidaApp: App {
|
|||||||
@State private var justCompletedWizard = false
|
@State private var justCompletedWizard = false
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
|
// Register app's color theme for Bedrock components
|
||||||
|
Theme.register(
|
||||||
|
text: AppTextColors.self,
|
||||||
|
surface: AppSurface.self,
|
||||||
|
accent: AppAccent.self,
|
||||||
|
status: AppStatus.self
|
||||||
|
)
|
||||||
|
Theme.register(border: AppBorder.self)
|
||||||
|
|
||||||
// Include all models in schema - Ritual, RitualArc, and ArcHabit
|
// Include all models in schema - Ritual, RitualArc, and ArcHabit
|
||||||
let schema = Schema([Ritual.self, RitualArc.self, ArcHabit.self])
|
let schema = Schema([Ritual.self, RitualArc.self, ArcHabit.self])
|
||||||
let configuration = ModelConfiguration(
|
let configuration = ModelConfiguration(
|
||||||
|
|||||||
@ -21,9 +21,9 @@ struct EmptyStateCardView: View {
|
|||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack(alignment: .leading, spacing: Design.Spacing.medium) {
|
VStack(alignment: .leading, spacing: Design.Spacing.medium) {
|
||||||
StyledLabel(title, .title2Bold, emphasis: .custom(AppTextColors.primary))
|
StyledLabel(title, .title2Bold, emphasis: .primary)
|
||||||
|
|
||||||
StyledLabel(message, .body, emphasis: .custom(AppTextColors.secondary))
|
StyledLabel(message, .body, emphasis: .secondary)
|
||||||
|
|
||||||
Button(action: action) {
|
Button(action: action) {
|
||||||
// Needs .frame() modifiers
|
// Needs .frame() modifiers
|
||||||
|
|||||||
@ -12,9 +12,9 @@ struct SectionHeaderView: View {
|
|||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack(alignment: .leading, spacing: Design.Spacing.xxxSmall) {
|
VStack(alignment: .leading, spacing: Design.Spacing.xxxSmall) {
|
||||||
StyledLabel(title, .heading, emphasis: .custom(AppTextColors.primary))
|
StyledLabel(title, .heading, emphasis: .primary)
|
||||||
if let subtitle {
|
if let subtitle {
|
||||||
StyledLabel(subtitle, .subheading, emphasis: .custom(AppTextColors.secondary))
|
StyledLabel(subtitle, .subheading, emphasis: .secondary)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.frame(maxWidth: .infinity, alignment: .leading)
|
.frame(maxWidth: .infinity, alignment: .leading)
|
||||||
|
|||||||
@ -22,7 +22,7 @@ struct InsightCardView: View {
|
|||||||
private var cardContent: some View {
|
private var cardContent: some View {
|
||||||
VStack(alignment: .leading, spacing: Design.Spacing.medium) {
|
VStack(alignment: .leading, spacing: Design.Spacing.medium) {
|
||||||
HStack {
|
HStack {
|
||||||
StyledLabel(card.title, .subheadingEmphasis, emphasis: .custom(AppTextColors.secondary))
|
StyledLabel(card.title, .subheadingEmphasis, emphasis: .secondary)
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
|
|
||||||
@ -32,11 +32,11 @@ struct InsightCardView: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Show value prominently
|
// Show value prominently
|
||||||
StyledLabel(card.value, .titleBold, emphasis: .custom(AppTextColors.primary))
|
StyledLabel(card.value, .titleBold, emphasis: .primary)
|
||||||
|
|
||||||
// Show caption if present (non-chart cards)
|
// Show caption if present (non-chart cards)
|
||||||
if !card.caption.isEmpty {
|
if !card.caption.isEmpty {
|
||||||
StyledLabel(card.caption, .caption, emphasis: .custom(AppTextColors.secondary))
|
StyledLabel(card.caption, .caption, emphasis: .secondary)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show full-width mini bar chart at bottom (Athlytic style)
|
// Show full-width mini bar chart at bottom (Athlytic style)
|
||||||
|
|||||||
@ -114,7 +114,7 @@ struct InsightDetailSheet: View {
|
|||||||
? String(localized: "+\(changePercent)% vs last week")
|
? String(localized: "+\(changePercent)% vs last week")
|
||||||
: String(localized: "-\(changePercent)% vs last week")
|
: String(localized: "-\(changePercent)% vs last week")
|
||||||
|
|
||||||
StyledLabel(changeText, .caption, emphasis: .custom(AppTextColors.secondary))
|
StyledLabel(changeText, .caption, emphasis: .secondary)
|
||||||
}
|
}
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
@ -126,7 +126,7 @@ struct InsightDetailSheet: View {
|
|||||||
|
|
||||||
private var tipsSection: some View {
|
private var tipsSection: some View {
|
||||||
VStack(alignment: .leading, spacing: Design.Spacing.small) {
|
VStack(alignment: .leading, spacing: Design.Spacing.small) {
|
||||||
IconLabel("lightbulb.fill", String(localized: "Tips"), .heading, emphasis: .custom(AppTextColors.primary))
|
IconLabel("lightbulb.fill", String(localized: "Tips"), .heading, emphasis: .primary)
|
||||||
|
|
||||||
VStack(alignment: .leading, spacing: Design.Spacing.small) {
|
VStack(alignment: .leading, spacing: Design.Spacing.small) {
|
||||||
ForEach(tips, id: \.self) { tip in
|
ForEach(tips, id: \.self) { tip in
|
||||||
@ -134,7 +134,7 @@ struct InsightDetailSheet: View {
|
|||||||
SymbolIcon("chevron.right", size: .badge, color: AppAccent.primary)
|
SymbolIcon("chevron.right", size: .badge, color: AppAccent.primary)
|
||||||
.padding(.top, Design.Spacing.xSmall)
|
.padding(.top, Design.Spacing.xSmall)
|
||||||
|
|
||||||
StyledLabel(tip, .subheading, emphasis: .custom(AppTextColors.secondary))
|
StyledLabel(tip, .subheading, emphasis: .secondary)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -149,9 +149,9 @@ struct InsightDetailSheet: View {
|
|||||||
|
|
||||||
private var explanationSection: some View {
|
private var explanationSection: some View {
|
||||||
VStack(alignment: .leading, spacing: Design.Spacing.small) {
|
VStack(alignment: .leading, spacing: Design.Spacing.small) {
|
||||||
StyledLabel(String(localized: "What this means"), .heading, emphasis: .custom(AppTextColors.primary))
|
StyledLabel(String(localized: "What this means"), .heading, emphasis: .primary)
|
||||||
|
|
||||||
StyledLabel(card.explanation, .body, emphasis: .custom(AppTextColors.secondary))
|
StyledLabel(card.explanation, .body, emphasis: .secondary)
|
||||||
}
|
}
|
||||||
.padding(Design.Spacing.large)
|
.padding(Design.Spacing.large)
|
||||||
.frame(maxWidth: .infinity, alignment: .leading)
|
.frame(maxWidth: .infinity, alignment: .leading)
|
||||||
@ -163,7 +163,7 @@ struct InsightDetailSheet: View {
|
|||||||
|
|
||||||
private func chartSection(_ data: [TrendDataPoint]) -> some View {
|
private func chartSection(_ data: [TrendDataPoint]) -> some View {
|
||||||
VStack(alignment: .leading, spacing: Design.Spacing.small) {
|
VStack(alignment: .leading, spacing: Design.Spacing.small) {
|
||||||
StyledLabel(String(localized: "7-Day Trend"), .heading, emphasis: .custom(AppTextColors.primary))
|
StyledLabel(String(localized: "7-Day Trend"), .heading, emphasis: .primary)
|
||||||
|
|
||||||
Chart(data) { point in
|
Chart(data) { point in
|
||||||
BarMark(
|
BarMark(
|
||||||
@ -214,16 +214,16 @@ struct InsightDetailSheet: View {
|
|||||||
|
|
||||||
private func breakdownSection(_ breakdown: [BreakdownItem]) -> some View {
|
private func breakdownSection(_ breakdown: [BreakdownItem]) -> some View {
|
||||||
VStack(alignment: .leading, spacing: Design.Spacing.small) {
|
VStack(alignment: .leading, spacing: Design.Spacing.small) {
|
||||||
StyledLabel(String(localized: "Breakdown"), .heading, emphasis: .custom(AppTextColors.primary))
|
StyledLabel(String(localized: "Breakdown"), .heading, emphasis: .primary)
|
||||||
|
|
||||||
VStack(spacing: Design.Spacing.xSmall) {
|
VStack(spacing: Design.Spacing.xSmall) {
|
||||||
ForEach(breakdown) { item in
|
ForEach(breakdown) { item in
|
||||||
HStack {
|
HStack {
|
||||||
StyledLabel(item.label, .subheading, emphasis: .custom(AppTextColors.primary))
|
StyledLabel(item.label, .subheading, emphasis: .primary)
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
|
|
||||||
StyledLabel(item.value, .subheading, emphasis: .custom(AppTextColors.secondary))
|
StyledLabel(item.value, .subheading, emphasis: .secondary)
|
||||||
}
|
}
|
||||||
.padding(.vertical, Design.Spacing.small)
|
.padding(.vertical, Design.Spacing.small)
|
||||||
|
|
||||||
|
|||||||
@ -55,7 +55,7 @@ struct FirstCheckInStepView: View {
|
|||||||
private var tutorialView: some View {
|
private var tutorialView: some View {
|
||||||
VStack(spacing: Design.Spacing.xxLarge) {
|
VStack(spacing: Design.Spacing.xxLarge) {
|
||||||
// Header
|
// Header
|
||||||
StyledLabel(String(localized: "Let's try it out!"), .title2Bold, emphasis: .custom(AppTextColors.primary), alignment: .center)
|
StyledLabel(String(localized: "Let's try it out!"), .title2Bold, emphasis: .primary, alignment: .center)
|
||||||
.opacity(animateContent ? 1 : 0)
|
.opacity(animateContent ? 1 : 0)
|
||||||
|
|
||||||
// Ritual card with habits
|
// Ritual card with habits
|
||||||
@ -65,9 +65,9 @@ struct FirstCheckInStepView: View {
|
|||||||
SymbolIcon(ritual.iconName, size: .row, color: AppAccent.primary)
|
SymbolIcon(ritual.iconName, size: .row, color: AppAccent.primary)
|
||||||
|
|
||||||
VStack(alignment: .leading, spacing: 2) {
|
VStack(alignment: .leading, spacing: 2) {
|
||||||
StyledLabel(String(localized: "Day 1 of \(ritual.durationDays)"), .caption, emphasis: .custom(AppTextColors.secondary))
|
StyledLabel(String(localized: "Day 1 of \(ritual.durationDays)"), .caption, emphasis: .secondary)
|
||||||
|
|
||||||
StyledLabel(ritual.title, .heading, emphasis: .custom(AppTextColors.primary))
|
StyledLabel(ritual.title, .heading, emphasis: .primary)
|
||||||
}
|
}
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
@ -93,14 +93,14 @@ struct FirstCheckInStepView: View {
|
|||||||
.offset(y: animateContent ? 0 : 20)
|
.offset(y: animateContent ? 0 : 20)
|
||||||
|
|
||||||
// Instruction
|
// Instruction
|
||||||
StyledLabel(String(localized: "Tap a habit to check in"), .subheading, emphasis: .custom(AppTextColors.secondary))
|
StyledLabel(String(localized: "Tap a habit to check in"), .subheading, emphasis: .secondary)
|
||||||
.opacity(animateContent ? 1 : 0)
|
.opacity(animateContent ? 1 : 0)
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
|
|
||||||
VStack(spacing: Design.Spacing.medium) {
|
VStack(spacing: Design.Spacing.medium) {
|
||||||
Button(action: onComplete) {
|
Button(action: onComplete) {
|
||||||
StyledLabel(String(localized: "Continue"), .heading, emphasis: .custom(AppTextColors.inverse))
|
StyledLabel(String(localized: "Continue"), .heading, emphasis: .inverse)
|
||||||
.frame(maxWidth: .infinity)
|
.frame(maxWidth: .infinity)
|
||||||
.frame(height: AppMetrics.Size.buttonHeight)
|
.frame(height: AppMetrics.Size.buttonHeight)
|
||||||
.background(AppAccent.primary)
|
.background(AppAccent.primary)
|
||||||
@ -108,7 +108,7 @@ struct FirstCheckInStepView: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Button(action: onComplete) {
|
Button(action: onComplete) {
|
||||||
StyledLabel(String(localized: "Skip for now"), .subheading, emphasis: .custom(AppTextColors.secondary))
|
StyledLabel(String(localized: "Skip for now"), .subheading, emphasis: .secondary)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.padding(.horizontal, Design.Spacing.xxLarge)
|
.padding(.horizontal, Design.Spacing.xxLarge)
|
||||||
@ -135,9 +135,9 @@ struct FirstCheckInStepView: View {
|
|||||||
.opacity(showCelebration ? 1 : 0)
|
.opacity(showCelebration ? 1 : 0)
|
||||||
|
|
||||||
VStack(spacing: Design.Spacing.medium) {
|
VStack(spacing: Design.Spacing.medium) {
|
||||||
StyledLabel(String(localized: "Nice work!"), .heroBold, emphasis: .custom(AppTextColors.primary))
|
StyledLabel(String(localized: "Nice work!"), .heroBold, emphasis: .primary)
|
||||||
|
|
||||||
StyledLabel(String(localized: "You completed your first check-in"), .title3, emphasis: .custom(AppTextColors.secondary), alignment: .center)
|
StyledLabel(String(localized: "You completed your first check-in"), .title3, emphasis: .secondary, alignment: .center)
|
||||||
}
|
}
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
@ -145,7 +145,7 @@ struct FirstCheckInStepView: View {
|
|||||||
// Continue button
|
// Continue button
|
||||||
if showContinueButton {
|
if showContinueButton {
|
||||||
Button(action: onComplete) {
|
Button(action: onComplete) {
|
||||||
StyledLabel(String(localized: "Continue to Rituals"), .heading, emphasis: .custom(AppTextColors.inverse))
|
StyledLabel(String(localized: "Continue to Rituals"), .heading, emphasis: .inverse)
|
||||||
.frame(maxWidth: .infinity)
|
.frame(maxWidth: .infinity)
|
||||||
.frame(height: AppMetrics.Size.buttonHeight)
|
.frame(height: AppMetrics.Size.buttonHeight)
|
||||||
.background(AppAccent.primary)
|
.background(AppAccent.primary)
|
||||||
@ -194,7 +194,7 @@ private struct OnboardingHabitRowView: View {
|
|||||||
SymbolIcon(symbolName, size: .row, color: isCompleted ? AppStatus.success : AppAccent.primary)
|
SymbolIcon(symbolName, size: .row, color: isCompleted ? AppStatus.success : AppAccent.primary)
|
||||||
.frame(width: AppMetrics.Size.iconLarge)
|
.frame(width: AppMetrics.Size.iconLarge)
|
||||||
|
|
||||||
StyledLabel(title, .body, emphasis: .custom(AppTextColors.primary))
|
StyledLabel(title, .body, emphasis: .primary)
|
||||||
|
|
||||||
Spacer(minLength: Design.Spacing.medium)
|
Spacer(minLength: Design.Spacing.medium)
|
||||||
|
|
||||||
|
|||||||
@ -26,7 +26,7 @@ struct RitualPreviewStepView: View {
|
|||||||
.frame(height: Design.Spacing.large)
|
.frame(height: Design.Spacing.large)
|
||||||
|
|
||||||
// Header
|
// Header
|
||||||
StyledLabel(headerText, .title2Bold, emphasis: .custom(AppTextColors.primary), alignment: .center)
|
StyledLabel(headerText, .title2Bold, emphasis: .primary, alignment: .center)
|
||||||
.opacity(animateContent ? 1 : 0)
|
.opacity(animateContent ? 1 : 0)
|
||||||
|
|
||||||
// Ritual preview card
|
// Ritual preview card
|
||||||
@ -36,9 +36,9 @@ struct RitualPreviewStepView: View {
|
|||||||
SymbolIcon(preset.iconName, size: .card, color: AppAccent.primary)
|
SymbolIcon(preset.iconName, size: .card, color: AppAccent.primary)
|
||||||
|
|
||||||
VStack(alignment: .leading, spacing: Design.Spacing.xSmall) {
|
VStack(alignment: .leading, spacing: Design.Spacing.xSmall) {
|
||||||
StyledLabel(preset.title, .title3Bold, emphasis: .custom(AppTextColors.primary))
|
StyledLabel(preset.title, .title3Bold, emphasis: .primary)
|
||||||
|
|
||||||
StyledLabel(preset.theme, .subheading, emphasis: .custom(AppTextColors.secondary))
|
StyledLabel(preset.theme, .subheading, emphasis: .secondary)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,7 +52,7 @@ struct RitualPreviewStepView: View {
|
|||||||
SymbolIcon(habit.symbolName, size: .inline, color: AppTextColors.secondary)
|
SymbolIcon(habit.symbolName, size: .inline, color: AppTextColors.secondary)
|
||||||
.frame(width: 24)
|
.frame(width: 24)
|
||||||
|
|
||||||
StyledLabel(habit.title, .body, emphasis: .custom(AppTextColors.primary))
|
StyledLabel(habit.title, .body, emphasis: .primary)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -62,9 +62,9 @@ struct RitualPreviewStepView: View {
|
|||||||
|
|
||||||
// Duration and time
|
// Duration and time
|
||||||
HStack(spacing: Design.Spacing.large) {
|
HStack(spacing: Design.Spacing.large) {
|
||||||
IconLabel("calendar", String(localized: "\(preset.durationDays) days"), .caption, emphasis: .custom(AppTextColors.secondary))
|
IconLabel("calendar", String(localized: "\(preset.durationDays) days"), .caption, emphasis: .secondary)
|
||||||
|
|
||||||
IconLabel(preset.timeOfDay.symbolName, preset.timeOfDay.displayName, .caption, emphasis: .custom(AppTextColors.secondary))
|
IconLabel(preset.timeOfDay.symbolName, preset.timeOfDay.displayName, .caption, emphasis: .secondary)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.padding(Design.Spacing.large)
|
.padding(Design.Spacing.large)
|
||||||
@ -80,7 +80,7 @@ struct RitualPreviewStepView: View {
|
|||||||
VStack(spacing: Design.Spacing.medium) {
|
VStack(spacing: Design.Spacing.medium) {
|
||||||
// Primary CTA
|
// Primary CTA
|
||||||
Button(action: onStartRitual) {
|
Button(action: onStartRitual) {
|
||||||
StyledLabel(String(localized: "Start This Ritual"), .heading, emphasis: .custom(AppTextColors.inverse))
|
StyledLabel(String(localized: "Start This Ritual"), .heading, emphasis: .inverse)
|
||||||
.frame(maxWidth: .infinity)
|
.frame(maxWidth: .infinity)
|
||||||
.frame(height: AppMetrics.Size.buttonHeight)
|
.frame(height: AppMetrics.Size.buttonHeight)
|
||||||
.background(AppAccent.primary)
|
.background(AppAccent.primary)
|
||||||
@ -89,7 +89,7 @@ struct RitualPreviewStepView: View {
|
|||||||
|
|
||||||
// Skip option
|
// Skip option
|
||||||
Button(action: onSkip) {
|
Button(action: onSkip) {
|
||||||
StyledLabel(String(localized: "Skip for now"), .subheading, emphasis: .custom(AppTextColors.secondary))
|
StyledLabel(String(localized: "Skip for now"), .subheading, emphasis: .secondary)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.padding(.horizontal, Design.Spacing.xxLarge)
|
.padding(.horizontal, Design.Spacing.xxLarge)
|
||||||
|
|||||||
@ -62,7 +62,7 @@ struct WhatsNextStepView: View {
|
|||||||
|
|
||||||
// CTA button
|
// CTA button
|
||||||
Button(action: onComplete) {
|
Button(action: onComplete) {
|
||||||
StyledLabel(String(localized: "Let's Go"), .heading, emphasis: .custom(AppTextColors.inverse))
|
StyledLabel(String(localized: "Let's Go"), .heading, emphasis: .inverse)
|
||||||
.frame(maxWidth: .infinity)
|
.frame(maxWidth: .infinity)
|
||||||
.frame(height: AppMetrics.Size.buttonHeight)
|
.frame(height: AppMetrics.Size.buttonHeight)
|
||||||
.background(AppAccent.primary)
|
.background(AppAccent.primary)
|
||||||
@ -99,9 +99,9 @@ private struct FeatureHelpCard: View {
|
|||||||
|
|
||||||
// Text
|
// Text
|
||||||
VStack(alignment: .leading, spacing: Design.Spacing.xSmall) {
|
VStack(alignment: .leading, spacing: Design.Spacing.xSmall) {
|
||||||
StyledLabel(title, .heading, emphasis: .custom(AppTextColors.primary))
|
StyledLabel(title, .heading, emphasis: .primary)
|
||||||
|
|
||||||
StyledLabel(description, .caption, emphasis: .custom(AppTextColors.secondary))
|
StyledLabel(description, .caption, emphasis: .secondary)
|
||||||
}
|
}
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
|
|||||||
@ -29,7 +29,7 @@ struct HabitPerformanceView: View {
|
|||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack(alignment: .leading, spacing: Design.Spacing.small) {
|
VStack(alignment: .leading, spacing: Design.Spacing.small) {
|
||||||
StyledLabel(String(localized: "Habit Performance"), .heading, emphasis: .custom(AppTextColors.primary))
|
StyledLabel(String(localized: "Habit Performance"), .heading, emphasis: .primary)
|
||||||
|
|
||||||
LazyVGrid(columns: habitColumns, alignment: .leading, spacing: Design.Spacing.xSmall) {
|
LazyVGrid(columns: habitColumns, alignment: .leading, spacing: Design.Spacing.xSmall) {
|
||||||
ForEach(sortedByRate, id: \.habit.id) { item in
|
ForEach(sortedByRate, id: \.habit.id) { item in
|
||||||
@ -50,7 +50,7 @@ struct HabitPerformanceView: View {
|
|||||||
SymbolIcon(habit.symbolName, size: .inline, color: colorForRate(rate))
|
SymbolIcon(habit.symbolName, size: .inline, color: colorForRate(rate))
|
||||||
.frame(width: AppMetrics.Size.iconMedium)
|
.frame(width: AppMetrics.Size.iconMedium)
|
||||||
|
|
||||||
StyledLabel(habit.title, .subheading, emphasis: .custom(AppTextColors.primary))
|
StyledLabel(habit.title, .subheading, emphasis: .primary)
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
|
|
||||||
|
|||||||
@ -58,7 +58,7 @@ struct RitualCardView: View {
|
|||||||
.typography(.subheading)
|
.typography(.subheading)
|
||||||
.foregroundStyle(hasActiveArc ? AppTextColors.secondary : AppTextColors.tertiary)
|
.foregroundStyle(hasActiveArc ? AppTextColors.secondary : AppTextColors.tertiary)
|
||||||
|
|
||||||
StyledLabel(completionSummary, .caption, emphasis: .custom(AppTextColors.secondary))
|
StyledLabel(completionSummary, .caption, emphasis: .secondary)
|
||||||
}
|
}
|
||||||
.padding(Design.Spacing.large)
|
.padding(Design.Spacing.large)
|
||||||
.background(AppSurface.card)
|
.background(AppSurface.card)
|
||||||
|
|||||||
@ -14,7 +14,7 @@ struct RitualMilestonesView: View {
|
|||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack(alignment: .leading, spacing: Design.Spacing.small) {
|
VStack(alignment: .leading, spacing: Design.Spacing.small) {
|
||||||
StyledLabel(String(localized: "Milestones"), .heading, emphasis: .custom(AppTextColors.primary))
|
StyledLabel(String(localized: "Milestones"), .heading, emphasis: .primary)
|
||||||
|
|
||||||
HStack(spacing: Design.Spacing.small) {
|
HStack(spacing: Design.Spacing.small) {
|
||||||
ForEach(milestones) { milestone in
|
ForEach(milestones) { milestone in
|
||||||
|
|||||||
@ -40,7 +40,7 @@ struct RitualProgressStatsView: View {
|
|||||||
ProgressView(value: progress)
|
ProgressView(value: progress)
|
||||||
.tint(AppAccent.primary)
|
.tint(AppAccent.primary)
|
||||||
|
|
||||||
StyledLabel("\(Int(progress * 100))% complete", .caption, emphasis: .custom(AppTextColors.secondary))
|
StyledLabel("\(Int(progress * 100))% complete", .caption, emphasis: .secondary)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.padding(Design.Spacing.large)
|
.padding(Design.Spacing.large)
|
||||||
@ -51,12 +51,12 @@ struct RitualProgressStatsView: View {
|
|||||||
|
|
||||||
private func statColumn(value: String, secondary: String?, label: String) -> some View {
|
private func statColumn(value: String, secondary: String?, label: String) -> some View {
|
||||||
VStack(spacing: Design.Spacing.xSmall) {
|
VStack(spacing: Design.Spacing.xSmall) {
|
||||||
StyledLabel(value, .titleBold, emphasis: .custom(AppTextColors.primary))
|
StyledLabel(value, .titleBold, emphasis: .primary)
|
||||||
|
|
||||||
// Always show secondary row for consistent height
|
// Always show secondary row for consistent height
|
||||||
StyledLabel(secondary ?? " ", .caption, emphasis: .custom(secondary != nil ? AppTextColors.tertiary : .clear))
|
StyledLabel(secondary ?? " ", .caption, emphasis: .custom(secondary != nil ? AppTextColors.tertiary : .clear))
|
||||||
|
|
||||||
StyledLabel(label, .caption2, emphasis: .custom(AppTextColors.secondary))
|
StyledLabel(label, .caption2, emphasis: .secondary)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -108,7 +108,7 @@ struct RitualDetailView: View {
|
|||||||
if !ritual.notes.isEmpty {
|
if !ritual.notes.isEmpty {
|
||||||
VStack(alignment: .leading, spacing: Design.Spacing.xSmall) {
|
VStack(alignment: .leading, spacing: Design.Spacing.xSmall) {
|
||||||
SectionHeaderView(title: String(localized: "Notes"))
|
SectionHeaderView(title: String(localized: "Notes"))
|
||||||
StyledLabel(ritual.notes, .body, emphasis: .custom(AppTextColors.secondary))
|
StyledLabel(ritual.notes, .body, emphasis: .secondary)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -257,7 +257,7 @@ struct RitualDetailView: View {
|
|||||||
VStack(alignment: .leading, spacing: Design.Spacing.medium) {
|
VStack(alignment: .leading, spacing: Design.Spacing.medium) {
|
||||||
HStack {
|
HStack {
|
||||||
SymbolIcon("clock.arrow.circlepath", size: .inline, color: AppTextColors.secondary)
|
SymbolIcon("clock.arrow.circlepath", size: .inline, color: AppTextColors.secondary)
|
||||||
StyledLabel(String(localized: "This ritual is not currently active"), .subheading, emphasis: .custom(AppTextColors.secondary))
|
StyledLabel(String(localized: "This ritual is not currently active"), .subheading, emphasis: .secondary)
|
||||||
}
|
}
|
||||||
|
|
||||||
if let lastArc = ritual.latestArc {
|
if let lastArc = ritual.latestArc {
|
||||||
@ -266,7 +266,7 @@ struct RitualDetailView: View {
|
|||||||
let possibleCheckIns = habits.count * lastArc.durationDays
|
let possibleCheckIns = habits.count * lastArc.durationDays
|
||||||
let completionRate = possibleCheckIns > 0 ? Int(Double(totalCheckIns) / Double(possibleCheckIns) * 100) : 0
|
let completionRate = possibleCheckIns > 0 ? Int(Double(totalCheckIns) / Double(possibleCheckIns) * 100) : 0
|
||||||
|
|
||||||
StyledLabel(String(localized: "Last arc completed with \(completionRate)% habit completion over \(lastArc.durationDays) days."), .caption, emphasis: .custom(AppTextColors.tertiary))
|
StyledLabel(String(localized: "Last arc completed with \(completionRate)% habit completion over \(lastArc.durationDays) days."), .caption, emphasis: .tertiary)
|
||||||
}
|
}
|
||||||
|
|
||||||
Button {
|
Button {
|
||||||
@ -318,7 +318,7 @@ struct RitualDetailView: View {
|
|||||||
.background(AppAccent.primary.opacity(0.2))
|
.background(AppAccent.primary.opacity(0.2))
|
||||||
.clipShape(.capsule)
|
.clipShape(.capsule)
|
||||||
} else {
|
} else {
|
||||||
StyledLabel(String(localized: "No active arc"), .caption, emphasis: .custom(AppTextColors.tertiary))
|
StyledLabel(String(localized: "No active arc"), .caption, emphasis: .tertiary)
|
||||||
.padding(.horizontal, Design.Spacing.small)
|
.padding(.horizontal, Design.Spacing.small)
|
||||||
.padding(.vertical, Design.Spacing.xSmall)
|
.padding(.vertical, Design.Spacing.xSmall)
|
||||||
.background(AppTextColors.tertiary.opacity(0.2))
|
.background(AppTextColors.tertiary.opacity(0.2))
|
||||||
@ -381,7 +381,7 @@ struct RitualDetailView: View {
|
|||||||
)
|
)
|
||||||
|
|
||||||
if completedArcs.isEmpty {
|
if completedArcs.isEmpty {
|
||||||
StyledLabel(String(localized: "No completed arcs yet."), .caption, emphasis: .custom(AppTextColors.tertiary))
|
StyledLabel(String(localized: "No completed arcs yet."), .caption, emphasis: .tertiary)
|
||||||
} else {
|
} else {
|
||||||
LazyVGrid(columns: arcColumns, alignment: .leading, spacing: Design.Spacing.small) {
|
LazyVGrid(columns: arcColumns, alignment: .leading, spacing: Design.Spacing.small) {
|
||||||
ForEach(completedArcs) { arc in
|
ForEach(completedArcs) { arc in
|
||||||
@ -407,9 +407,9 @@ struct RitualDetailView: View {
|
|||||||
} label: {
|
} label: {
|
||||||
HStack {
|
HStack {
|
||||||
VStack(alignment: .leading, spacing: Design.Spacing.xSmall) {
|
VStack(alignment: .leading, spacing: Design.Spacing.xSmall) {
|
||||||
StyledLabel(String(localized: "Arc \(arc.arcNumber)"), .subheadingEmphasis, emphasis: .custom(AppTextColors.primary))
|
StyledLabel(String(localized: "Arc \(arc.arcNumber)"), .subheadingEmphasis, emphasis: .primary)
|
||||||
|
|
||||||
StyledLabel("\(dateFormatter.string(from: arc.startDate)) – \(dateFormatter.string(from: arc.endDate))", .caption, emphasis: .custom(AppTextColors.tertiary))
|
StyledLabel("\(dateFormatter.string(from: arc.startDate)) – \(dateFormatter.string(from: arc.endDate))", .caption, emphasis: .tertiary)
|
||||||
}
|
}
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
@ -417,7 +417,7 @@ struct RitualDetailView: View {
|
|||||||
VStack(alignment: .trailing, spacing: Design.Spacing.xSmall) {
|
VStack(alignment: .trailing, spacing: Design.Spacing.xSmall) {
|
||||||
StyledLabel("\(completionRate)%", .subheadingEmphasis, emphasis: .custom(completionRate >= 70 ? AppStatus.success : AppTextColors.secondary))
|
StyledLabel("\(completionRate)%", .subheadingEmphasis, emphasis: .custom(completionRate >= 70 ? AppStatus.success : AppTextColors.secondary))
|
||||||
|
|
||||||
StyledLabel(String(localized: "\(arc.durationDays) days"), .caption, emphasis: .custom(AppTextColors.tertiary))
|
StyledLabel(String(localized: "\(arc.durationDays) days"), .caption, emphasis: .tertiary)
|
||||||
}
|
}
|
||||||
|
|
||||||
SymbolIcon.chevron(color: AppTextColors.tertiary)
|
SymbolIcon.chevron(color: AppTextColors.tertiary)
|
||||||
@ -436,7 +436,7 @@ struct RitualDetailView: View {
|
|||||||
HStack(spacing: Design.Spacing.medium) {
|
HStack(spacing: Design.Spacing.medium) {
|
||||||
// Days remaining
|
// Days remaining
|
||||||
if daysRemaining > 0 {
|
if daysRemaining > 0 {
|
||||||
IconLabel("hourglass", String(localized: "\(daysRemaining) days remaining"), .caption, emphasis: .custom(AppTextColors.secondary))
|
IconLabel("hourglass", String(localized: "\(daysRemaining) days remaining"), .caption, emphasis: .secondary)
|
||||||
.padding(.horizontal, Design.Spacing.medium)
|
.padding(.horizontal, Design.Spacing.medium)
|
||||||
.padding(.vertical, Design.Spacing.small)
|
.padding(.vertical, Design.Spacing.small)
|
||||||
.background(AppSurface.card)
|
.background(AppSurface.card)
|
||||||
|
|||||||
@ -141,7 +141,7 @@ struct RitualsView: View {
|
|||||||
// Time of day header
|
// Time of day header
|
||||||
HStack(spacing: Design.Spacing.small) {
|
HStack(spacing: Design.Spacing.small) {
|
||||||
SymbolIcon(group.timeOfDay.symbolName, size: .inline, color: AppAccent.primary)
|
SymbolIcon(group.timeOfDay.symbolName, size: .inline, color: AppAccent.primary)
|
||||||
StyledLabel(group.timeOfDay.displayName, .subheadingEmphasis, emphasis: .custom(AppTextColors.secondary))
|
StyledLabel(group.timeOfDay.displayName, .subheadingEmphasis, emphasis: .secondary)
|
||||||
}
|
}
|
||||||
.padding(.top, Design.Spacing.small)
|
.padding(.top, Design.Spacing.small)
|
||||||
|
|
||||||
@ -178,7 +178,7 @@ struct RitualsView: View {
|
|||||||
VStack(spacing: Design.Spacing.large) {
|
VStack(spacing: Design.Spacing.large) {
|
||||||
SymbolIcon("sparkles", size: .hero, color: AppAccent.primary)
|
SymbolIcon("sparkles", size: .hero, color: AppAccent.primary)
|
||||||
|
|
||||||
StyledLabel(String(localized: "No Active Rituals"), .heading, emphasis: .custom(AppTextColors.primary))
|
StyledLabel(String(localized: "No Active Rituals"), .heading, emphasis: .primary)
|
||||||
|
|
||||||
Text(String(localized: "Create a custom ritual or browse our preset library to get started."))
|
Text(String(localized: "Create a custom ritual or browse our preset library to get started."))
|
||||||
.typography(.subheading)
|
.typography(.subheading)
|
||||||
@ -217,7 +217,7 @@ struct RitualsView: View {
|
|||||||
VStack(spacing: Design.Spacing.large) {
|
VStack(spacing: Design.Spacing.large) {
|
||||||
SymbolIcon("clock.arrow.circlepath", size: .hero, color: AppTextColors.tertiary)
|
SymbolIcon("clock.arrow.circlepath", size: .hero, color: AppTextColors.tertiary)
|
||||||
|
|
||||||
StyledLabel(String(localized: "No Past Rituals"), .heading, emphasis: .custom(AppTextColors.primary))
|
StyledLabel(String(localized: "No Past Rituals"), .heading, emphasis: .primary)
|
||||||
|
|
||||||
Text(String(localized: "Rituals that have ended will appear here. You can restart them anytime."))
|
Text(String(localized: "Rituals that have ended will appear here. You can restart them anytime."))
|
||||||
.typography(.subheading)
|
.typography(.subheading)
|
||||||
@ -324,12 +324,12 @@ struct RitualsView: View {
|
|||||||
.clipShape(.rect(cornerRadius: Design.CornerRadius.small))
|
.clipShape(.rect(cornerRadius: Design.CornerRadius.small))
|
||||||
|
|
||||||
VStack(alignment: .leading, spacing: Design.Spacing.xSmall) {
|
VStack(alignment: .leading, spacing: Design.Spacing.xSmall) {
|
||||||
StyledLabel(ritual.title, .heading, emphasis: .custom(AppTextColors.primary))
|
StyledLabel(ritual.title, .heading, emphasis: .primary)
|
||||||
|
|
||||||
StyledLabel(ritual.theme, .caption, emphasis: .custom(AppTextColors.secondary))
|
StyledLabel(ritual.theme, .caption, emphasis: .secondary)
|
||||||
|
|
||||||
if let lastArc = ritual.latestArc {
|
if let lastArc = ritual.latestArc {
|
||||||
IconLabel("calendar", formattedEndDate(lastArc.endDate), .caption2, emphasis: .custom(AppTextColors.tertiary))
|
IconLabel("calendar", formattedEndDate(lastArc.endDate), .caption2, emphasis: .tertiary)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -337,7 +337,7 @@ struct RitualsView: View {
|
|||||||
|
|
||||||
// Arc count badge
|
// Arc count badge
|
||||||
if ritual.completedArcCount > 0 {
|
if ritual.completedArcCount > 0 {
|
||||||
StyledLabel("\(ritual.completedArcCount) arc\(ritual.completedArcCount == 1 ? "" : "s")", .caption2, emphasis: .custom(AppTextColors.secondary))
|
StyledLabel("\(ritual.completedArcCount) arc\(ritual.completedArcCount == 1 ? "" : "s")", .caption2, emphasis: .secondary)
|
||||||
.padding(.horizontal, Design.Spacing.small)
|
.padding(.horizontal, Design.Spacing.small)
|
||||||
.padding(.vertical, Design.Spacing.xSmall)
|
.padding(.vertical, Design.Spacing.xSmall)
|
||||||
.background(AppSurface.secondary)
|
.background(AppSurface.secondary)
|
||||||
|
|||||||
@ -92,14 +92,14 @@ struct PresetLibrarySheet: View {
|
|||||||
|
|
||||||
VStack(alignment: .leading, spacing: Design.Spacing.xSmall) {
|
VStack(alignment: .leading, spacing: Design.Spacing.xSmall) {
|
||||||
HStack {
|
HStack {
|
||||||
StyledLabel(preset.title, .heading, emphasis: .custom(AppTextColors.primary))
|
StyledLabel(preset.title, .heading, emphasis: .primary)
|
||||||
|
|
||||||
if isAdded {
|
if isAdded {
|
||||||
SymbolIcon("checkmark.circle.fill", size: .badge, color: AppStatus.success)
|
SymbolIcon("checkmark.circle.fill", size: .badge, color: AppStatus.success)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
StyledLabel(preset.theme, .subheading, emphasis: .custom(AppTextColors.secondary))
|
StyledLabel(preset.theme, .subheading, emphasis: .secondary)
|
||||||
}
|
}
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
@ -107,7 +107,7 @@ struct PresetLibrarySheet: View {
|
|||||||
VStack(alignment: .trailing, spacing: Design.Spacing.xSmall) {
|
VStack(alignment: .trailing, spacing: Design.Spacing.xSmall) {
|
||||||
SymbolIcon(preset.timeOfDay.symbolName, size: .badge, color: AppTextColors.tertiary)
|
SymbolIcon(preset.timeOfDay.symbolName, size: .badge, color: AppTextColors.tertiary)
|
||||||
|
|
||||||
StyledLabel(String(localized: "\(preset.habits.count) habits"), .caption, emphasis: .custom(AppTextColors.tertiary))
|
StyledLabel(String(localized: "\(preset.habits.count) habits"), .caption, emphasis: .tertiary)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,9 +118,7 @@ struct PresetLibrarySheet: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if preset.habits.count > 4 {
|
if preset.habits.count > 4 {
|
||||||
Text("+\(preset.habits.count - 4)")
|
StyledLabel("+\(preset.habits.count - 4)", .caption2, emphasis: .tertiary)
|
||||||
.font(.caption2)
|
|
||||||
.foregroundStyle(AppTextColors.tertiary)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -199,9 +197,9 @@ struct PresetDetailSheet: View {
|
|||||||
|
|
||||||
private var descriptionSection: some View {
|
private var descriptionSection: some View {
|
||||||
VStack(alignment: .leading, spacing: Design.Spacing.small) {
|
VStack(alignment: .leading, spacing: Design.Spacing.small) {
|
||||||
StyledLabel(String(localized: "About"), .heading, emphasis: .custom(AppTextColors.primary))
|
StyledLabel(String(localized: "About"), .heading, emphasis: .primary)
|
||||||
|
|
||||||
StyledLabel(preset.notes, .body, emphasis: .custom(AppTextColors.secondary))
|
StyledLabel(preset.notes, .body, emphasis: .secondary)
|
||||||
}
|
}
|
||||||
.padding(Design.Spacing.large)
|
.padding(Design.Spacing.large)
|
||||||
.frame(maxWidth: .infinity, alignment: .leading)
|
.frame(maxWidth: .infinity, alignment: .leading)
|
||||||
@ -211,7 +209,7 @@ struct PresetDetailSheet: View {
|
|||||||
|
|
||||||
private var habitsSection: some View {
|
private var habitsSection: some View {
|
||||||
VStack(alignment: .leading, spacing: Design.Spacing.small) {
|
VStack(alignment: .leading, spacing: Design.Spacing.small) {
|
||||||
StyledLabel(String(localized: "Habits"), .heading, emphasis: .custom(AppTextColors.primary))
|
StyledLabel(String(localized: "Habits"), .heading, emphasis: .primary)
|
||||||
|
|
||||||
VStack(spacing: Design.Spacing.xSmall) {
|
VStack(spacing: Design.Spacing.xSmall) {
|
||||||
ForEach(preset.habits) { habit in
|
ForEach(preset.habits) { habit in
|
||||||
@ -219,7 +217,7 @@ struct PresetDetailSheet: View {
|
|||||||
SymbolIcon(habit.symbolName, size: .inline, color: AppAccent.primary)
|
SymbolIcon(habit.symbolName, size: .inline, color: AppAccent.primary)
|
||||||
.frame(width: 24)
|
.frame(width: 24)
|
||||||
|
|
||||||
StyledLabel(habit.title, .subheading, emphasis: .custom(AppTextColors.primary))
|
StyledLabel(habit.title, .subheading, emphasis: .primary)
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -122,7 +122,7 @@ struct RitualEditSheet: View {
|
|||||||
|
|
||||||
// Category selection - simple picker from CategoryStore
|
// Category selection - simple picker from CategoryStore
|
||||||
VStack(alignment: .leading, spacing: Design.Spacing.medium) {
|
VStack(alignment: .leading, spacing: Design.Spacing.medium) {
|
||||||
StyledLabel(String(localized: "Category"), .subheading, emphasis: .custom(AppTextColors.secondary))
|
StyledLabel(String(localized: "Category"), .subheading, emphasis: .secondary)
|
||||||
|
|
||||||
// Horizontal scrollable category chips
|
// Horizontal scrollable category chips
|
||||||
ScrollView(.horizontal, showsIndicators: false) {
|
ScrollView(.horizontal, showsIndicators: false) {
|
||||||
@ -169,7 +169,7 @@ struct RitualEditSheet: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Show the time range for the selected time of day
|
// Show the time range for the selected time of day
|
||||||
IconLabel(timeOfDay.symbolName, timeOfDay.timeRange, .caption, emphasis: .custom(AppTextColors.tertiary))
|
IconLabel(timeOfDay.symbolName, timeOfDay.timeRange, .caption, emphasis: .tertiary)
|
||||||
}
|
}
|
||||||
.listRowBackground(AppSurface.card)
|
.listRowBackground(AppSurface.card)
|
||||||
|
|
||||||
@ -314,7 +314,7 @@ struct RitualEditSheet: View {
|
|||||||
HStack {
|
HStack {
|
||||||
Text(String(localized: "Habits"))
|
Text(String(localized: "Habits"))
|
||||||
Spacer()
|
Spacer()
|
||||||
StyledLabel(String(localized: "\(habits.count) habits"), .caption, emphasis: .custom(AppTextColors.tertiary))
|
StyledLabel(String(localized: "\(habits.count) habits"), .caption, emphasis: .tertiary)
|
||||||
}
|
}
|
||||||
} footer: {
|
} footer: {
|
||||||
if habits.count > 1 {
|
if habits.count > 1 {
|
||||||
@ -493,7 +493,7 @@ struct IconPickerSheet: View {
|
|||||||
LazyVStack(alignment: .leading, spacing: Design.Spacing.large) {
|
LazyVStack(alignment: .leading, spacing: Design.Spacing.large) {
|
||||||
ForEach(iconGroups, id: \.name) { group in
|
ForEach(iconGroups, id: \.name) { group in
|
||||||
VStack(alignment: .leading, spacing: Design.Spacing.small) {
|
VStack(alignment: .leading, spacing: Design.Spacing.small) {
|
||||||
StyledLabel(group.name, .caption, emphasis: .custom(AppTextColors.secondary))
|
StyledLabel(group.name, .caption, emphasis: .secondary)
|
||||||
.padding(.horizontal, Design.Spacing.small)
|
.padding(.horizontal, Design.Spacing.small)
|
||||||
|
|
||||||
LazyVGrid(columns: Array(repeating: GridItem(.flexible()), count: 6), spacing: Design.Spacing.small) {
|
LazyVGrid(columns: Array(repeating: GridItem(.flexible()), count: 6), spacing: Design.Spacing.small) {
|
||||||
@ -597,7 +597,7 @@ struct HabitIconPickerSheet: View {
|
|||||||
LazyVStack(alignment: .leading, spacing: Design.Spacing.large) {
|
LazyVStack(alignment: .leading, spacing: Design.Spacing.large) {
|
||||||
ForEach(iconGroups, id: \.name) { group in
|
ForEach(iconGroups, id: \.name) { group in
|
||||||
VStack(alignment: .leading, spacing: Design.Spacing.small) {
|
VStack(alignment: .leading, spacing: Design.Spacing.small) {
|
||||||
StyledLabel(group.name, .caption, emphasis: .custom(AppTextColors.secondary))
|
StyledLabel(group.name, .caption, emphasis: .secondary)
|
||||||
.padding(.horizontal, Design.Spacing.small)
|
.padding(.horizontal, Design.Spacing.small)
|
||||||
|
|
||||||
LazyVGrid(columns: Array(repeating: GridItem(.flexible()), count: 6), spacing: Design.Spacing.small) {
|
LazyVGrid(columns: Array(repeating: GridItem(.flexible()), count: 6), spacing: Design.Spacing.small) {
|
||||||
|
|||||||
@ -33,7 +33,7 @@ struct RitualFocusCardView: View {
|
|||||||
.accessibilityHidden(true)
|
.accessibilityHidden(true)
|
||||||
|
|
||||||
// Title
|
// Title
|
||||||
StyledLabel(title, .heading, emphasis: .custom(AppTextColors.primary))
|
StyledLabel(title, .heading, emphasis: .primary)
|
||||||
|
|
||||||
Spacer(minLength: Design.Spacing.medium)
|
Spacer(minLength: Design.Spacing.medium)
|
||||||
|
|
||||||
@ -48,12 +48,12 @@ struct RitualFocusCardView: View {
|
|||||||
.accessibilityLabel(Text(dayLabel))
|
.accessibilityLabel(Text(dayLabel))
|
||||||
}
|
}
|
||||||
|
|
||||||
StyledLabel(theme, .subheading, emphasis: .custom(AppTextColors.secondary))
|
StyledLabel(theme, .subheading, emphasis: .secondary)
|
||||||
|
|
||||||
VStack(alignment: .leading, spacing: Design.Spacing.xSmall) {
|
VStack(alignment: .leading, spacing: Design.Spacing.xSmall) {
|
||||||
ProgressView(value: progress)
|
ProgressView(value: progress)
|
||||||
.tint(AppAccent.primary)
|
.tint(AppAccent.primary)
|
||||||
StyledLabel(completionSummary, .caption, emphasis: .custom(AppTextColors.secondary))
|
StyledLabel(completionSummary, .caption, emphasis: .secondary)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.padding(Design.Spacing.large)
|
.padding(Design.Spacing.large)
|
||||||
|
|||||||
@ -29,7 +29,7 @@ struct TodayHabitRowView: View {
|
|||||||
.frame(width: AppMetrics.Size.iconLarge)
|
.frame(width: AppMetrics.Size.iconLarge)
|
||||||
.accessibilityHidden(true)
|
.accessibilityHidden(true)
|
||||||
|
|
||||||
StyledLabel(title, .subheading, emphasis: .custom(AppTextColors.primary))
|
StyledLabel(title, .subheading, emphasis: .primary)
|
||||||
|
|
||||||
Spacer(minLength: Design.Spacing.medium)
|
Spacer(minLength: Design.Spacing.medium)
|
||||||
|
|
||||||
|
|||||||
@ -10,8 +10,8 @@ struct TodayHeaderView: View {
|
|||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack(alignment: .leading, spacing: Design.Spacing.xxxSmall) {
|
VStack(alignment: .leading, spacing: Design.Spacing.xxxSmall) {
|
||||||
StyledLabel(String(localized: "Today"), .heroBold, emphasis: .custom(AppTextColors.primary))
|
StyledLabel(String(localized: "Today"), .heroBold, emphasis: .primary)
|
||||||
StyledLabel(dateText, .subheading, emphasis: .custom(AppTextColors.secondary))
|
StyledLabel(dateText, .subheading, emphasis: .secondary)
|
||||||
}
|
}
|
||||||
.frame(maxWidth: .infinity, alignment: .leading)
|
.frame(maxWidth: .infinity, alignment: .leading)
|
||||||
.accessibilityElement(children: .combine)
|
.accessibilityElement(children: .combine)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user