diff --git a/Andromida/App/Localization/Localizable.xcstrings b/Andromida/App/Localization/Localizable.xcstrings index 3ee9c5f..d8273be 100644 --- a/Andromida/App/Localization/Localizable.xcstrings +++ b/Andromida/App/Localization/Localizable.xcstrings @@ -3,11 +3,27 @@ "strings" : { "" : { + }, + " : " : { + "comment" : "A separator between the time of day and the time range in the Ritual Detail View.", + "isCommentAutoGenerated" : true }, "-%lld%% vs last week" : { "comment" : "A description of how a user's usage has changed compared to the previous week. The argument is the percentage by which the usage has increased or decreased.", "isCommentAutoGenerated" : true }, + "%@ – %@" : { + "comment" : "A subline of text showing the start and end dates of an arc.", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "%1$@ – %2$@" + } + } + } + }, "%@, Day %lld" : { "comment" : "A view representing a milestone achievement in a ritual journey. The first argument is the title of the milestone. The second argument is the day on which the milestone was achieved.", "isCommentAutoGenerated" : true, @@ -24,6 +40,18 @@ "comment" : "A text view displaying the day number in a history calendar cell. The text is centered and has a small font size.", "isCommentAutoGenerated" : true }, + "%lld arc%@" : { + "comment" : "A badge displaying the number of completed arcs for a ritual. The argument is the count of completed arcs.", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "%1$lld arc%2$@" + } + } + } + }, "%lld days" : { "comment" : "A label displaying the duration of a preset in days. The argument is the number of days the preset is active.", "isCommentAutoGenerated" : true @@ -126,6 +154,10 @@ } } }, + "%lld%% complete" : { + "comment" : "A percentage indicating the completion status of a ritual. The value is an integer percentage.", + "isCommentAutoGenerated" : true + }, "%lld%% completion over %lld days" : { "comment" : "A string summarizing the completion rate of a ritual arc. The first argument is the completion rate, expressed as a percentage. The second argument is the duration of the arc in days.", "isCommentAutoGenerated" : true, @@ -701,6 +733,10 @@ "comment" : "Label for the x-axis in the mini sparkline chart within an `InsightCardView`.", "isCommentAutoGenerated" : true }, + "Day %lld" : { + "comment" : "A sublabel showing the day and title of a milestone achievement. The first argument is the day of the milestone. The second argument is the title of the milestone.", + "isCommentAutoGenerated" : true + }, "Day %lld of %lld" : { "localizations" : { "en" : { diff --git a/Andromida/App/Views/Components/EmptyStateCardView.swift b/Andromida/App/Views/Components/EmptyStateCardView.swift index bb185cf..65935f6 100644 --- a/Andromida/App/Views/Components/EmptyStateCardView.swift +++ b/Andromida/App/Views/Components/EmptyStateCardView.swift @@ -21,9 +21,9 @@ struct EmptyStateCardView: View { var body: some View { VStack(alignment: .leading, spacing: Design.Spacing.medium) { - StyledLabel(title, .title2Bold, emphasis: .primary) + Text(title).styled(.title2Bold, emphasis: .primary) - StyledLabel(message, .body, emphasis: .secondary) + Text(message).styled(.body, emphasis: .secondary) Button(action: action) { // Needs .frame() modifiers diff --git a/Andromida/App/Views/Components/SectionHeaderView.swift b/Andromida/App/Views/Components/SectionHeaderView.swift index 216b9cb..6a1c01e 100644 --- a/Andromida/App/Views/Components/SectionHeaderView.swift +++ b/Andromida/App/Views/Components/SectionHeaderView.swift @@ -12,9 +12,9 @@ struct SectionHeaderView: View { var body: some View { VStack(alignment: .leading, spacing: Design.Spacing.xxxSmall) { - StyledLabel(title, .heading, emphasis: .primary) + Text(title).styled(.heading, emphasis: .primary) if let subtitle { - StyledLabel(subtitle, .subheading, emphasis: .secondary) + Text(subtitle).styled(.subheading, emphasis: .secondary) } } .frame(maxWidth: .infinity, alignment: .leading) diff --git a/Andromida/App/Views/Insights/Components/InsightCardView.swift b/Andromida/App/Views/Insights/Components/InsightCardView.swift index 3cc01b5..5330fb7 100644 --- a/Andromida/App/Views/Insights/Components/InsightCardView.swift +++ b/Andromida/App/Views/Insights/Components/InsightCardView.swift @@ -22,7 +22,7 @@ struct InsightCardView: View { private var cardContent: some View { VStack(alignment: .leading, spacing: Design.Spacing.medium) { HStack { - StyledLabel(card.title, .subheadingEmphasis, emphasis: .secondary) + Text(card.title).styled(.subheadingEmphasis, emphasis: .secondary) Spacer() @@ -32,11 +32,11 @@ struct InsightCardView: View { } // Show value prominently - StyledLabel(card.value, .titleBold, emphasis: .primary) + Text(card.value).styled(.titleBold, emphasis: .primary) // Show caption if present (non-chart cards) if !card.caption.isEmpty { - StyledLabel(card.caption, .caption, emphasis: .secondary) + Text(card.caption).styled(.caption, emphasis: .secondary) } // Show full-width mini bar chart at bottom (Athlytic style) diff --git a/Andromida/App/Views/Insights/Components/InsightDetailSheet.swift b/Andromida/App/Views/Insights/Components/InsightDetailSheet.swift index e77eace..30c0bfe 100644 --- a/Andromida/App/Views/Insights/Components/InsightDetailSheet.swift +++ b/Andromida/App/Views/Insights/Components/InsightDetailSheet.swift @@ -101,7 +101,8 @@ struct InsightDetailSheet: View { private var trendIndicatorSection: some View { HStack(spacing: Design.Spacing.medium) { // Trend direction badge - IconLabel(trendDirection.symbolName, trendDirection.accessibilityLabel, .caption, emphasis: .custom(trendDirection.color)) + Label(trendDirection.accessibilityLabel, systemImage: trendDirection.symbolName) + .styled(.caption, emphasis: .custom(trendDirection.color)) .padding(.horizontal, Design.Spacing.medium) .padding(.vertical, Design.Spacing.small) .background(trendDirection.color.opacity(Design.Opacity.subtle)) @@ -114,7 +115,7 @@ struct InsightDetailSheet: View { ? String(localized: "+\(changePercent)% vs last week") : String(localized: "-\(changePercent)% vs last week") - StyledLabel(changeText, .caption, emphasis: .secondary) + Text(changeText).styled(.caption, emphasis: .secondary) } Spacer() @@ -126,7 +127,8 @@ struct InsightDetailSheet: View { private var tipsSection: some View { VStack(alignment: .leading, spacing: Design.Spacing.small) { - IconLabel("lightbulb.fill", String(localized: "Tips"), .heading, emphasis: .primary) + Label(String(localized: "Tips"), systemImage: "lightbulb.fill") + .styled(.heading, emphasis: .primary) VStack(alignment: .leading, spacing: Design.Spacing.small) { ForEach(tips, id: \.self) { tip in @@ -134,7 +136,7 @@ struct InsightDetailSheet: View { SymbolIcon("chevron.right", size: .badge, color: AppAccent.primary) .padding(.top, Design.Spacing.xSmall) - StyledLabel(tip, .subheading, emphasis: .secondary) + Text(tip).styled(.subheading, emphasis: .secondary) } } } @@ -149,9 +151,9 @@ struct InsightDetailSheet: View { private var explanationSection: some View { VStack(alignment: .leading, spacing: Design.Spacing.small) { - StyledLabel(String(localized: "What this means"), .heading, emphasis: .primary) + Text(String(localized: "What this means")).styled(.heading, emphasis: .primary) - StyledLabel(card.explanation, .body, emphasis: .secondary) + Text(card.explanation).styled(.body, emphasis: .secondary) } .padding(Design.Spacing.large) .frame(maxWidth: .infinity, alignment: .leading) @@ -163,7 +165,7 @@ struct InsightDetailSheet: View { private func chartSection(_ data: [TrendDataPoint]) -> some View { VStack(alignment: .leading, spacing: Design.Spacing.small) { - StyledLabel(String(localized: "7-Day Trend"), .heading, emphasis: .primary) + Text(String(localized: "7-Day Trend")).styled(.heading, emphasis: .primary) Chart(data) { point in BarMark( @@ -182,10 +184,8 @@ struct InsightDetailSheet: View { AxisMarks(values: [0, 0.5, 1.0]) { value in AxisValueLabel { if let v = value.as(Double.self) { - // Exception: Inside AxisValueLabel closure Text("\(Int(v * 100))%") - .font(Typography.caption2.font) - .foregroundStyle(AppTextColors.tertiary) + .styled(.caption2, emphasis: .tertiary) } } AxisGridLine() @@ -194,10 +194,10 @@ struct InsightDetailSheet: View { } .chartXAxis { AxisMarks { _ in - // Exception: AxisValueLabel doesn't support StyledLabel + // Exception: AxisValueLabel() doesn't support .styled() AxisValueLabel() .font(Typography.caption2.font) - .foregroundStyle(AppTextColors.secondary) + .foregroundStyle(Theme.Text.secondary) } } .frame(height: 180) @@ -214,16 +214,16 @@ struct InsightDetailSheet: View { private func breakdownSection(_ breakdown: [BreakdownItem]) -> some View { VStack(alignment: .leading, spacing: Design.Spacing.small) { - StyledLabel(String(localized: "Breakdown"), .heading, emphasis: .primary) + Text(String(localized: "Breakdown")).styled(.heading, emphasis: .primary) VStack(spacing: Design.Spacing.xSmall) { ForEach(breakdown) { item in HStack { - StyledLabel(item.label, .subheading, emphasis: .primary) + Text(item.label).styled(.subheading, emphasis: .primary) Spacer() - StyledLabel(item.value, .subheading, emphasis: .secondary) + Text(item.value).styled(.subheading, emphasis: .secondary) } .padding(.vertical, Design.Spacing.small) diff --git a/Andromida/App/Views/Onboarding/FirstCheckInStepView.swift b/Andromida/App/Views/Onboarding/FirstCheckInStepView.swift index 09ba863..2dc95dc 100644 --- a/Andromida/App/Views/Onboarding/FirstCheckInStepView.swift +++ b/Andromida/App/Views/Onboarding/FirstCheckInStepView.swift @@ -55,7 +55,9 @@ struct FirstCheckInStepView: View { private var tutorialView: some View { VStack(spacing: Design.Spacing.xxLarge) { // Header - StyledLabel(String(localized: "Let's try it out!"), .title2Bold, emphasis: .primary, alignment: .center) + Text(String(localized: "Let's try it out!")) + .styled(.title2Bold, emphasis: .primary) + .multilineTextAlignment(.center) .opacity(animateContent ? 1 : 0) // Ritual card with habits @@ -65,9 +67,9 @@ struct FirstCheckInStepView: View { SymbolIcon(ritual.iconName, size: .row, color: AppAccent.primary) VStack(alignment: .leading, spacing: 2) { - StyledLabel(String(localized: "Day 1 of \(ritual.durationDays)"), .caption, emphasis: .secondary) + Text(String(localized: "Day 1 of \(ritual.durationDays)")).styled(.caption, emphasis: .secondary) - StyledLabel(ritual.title, .heading, emphasis: .primary) + Text(ritual.title).styled(.heading, emphasis: .primary) } Spacer() @@ -93,14 +95,14 @@ struct FirstCheckInStepView: View { .offset(y: animateContent ? 0 : 20) // Instruction - StyledLabel(String(localized: "Tap a habit to check in"), .subheading, emphasis: .secondary) + Text(String(localized: "Tap a habit to check in")).styled(.subheading, emphasis: .secondary) .opacity(animateContent ? 1 : 0) Spacer() VStack(spacing: Design.Spacing.medium) { Button(action: onComplete) { - StyledLabel(String(localized: "Continue"), .heading, emphasis: .inverse) + Text(String(localized: "Continue")).styled(.heading, emphasis: .inverse) .frame(maxWidth: .infinity) .frame(height: AppMetrics.Size.buttonHeight) .background(AppAccent.primary) @@ -108,7 +110,7 @@ struct FirstCheckInStepView: View { } Button(action: onComplete) { - StyledLabel(String(localized: "Skip for now"), .subheading, emphasis: .secondary) + Text(String(localized: "Skip for now")).styled(.subheading, emphasis: .secondary) } } .padding(.horizontal, Design.Spacing.xxLarge) @@ -135,9 +137,11 @@ struct FirstCheckInStepView: View { .opacity(showCelebration ? 1 : 0) VStack(spacing: Design.Spacing.medium) { - StyledLabel(String(localized: "Nice work!"), .heroBold, emphasis: .primary) + Text(String(localized: "Nice work!")).styled(.heroBold, emphasis: .primary) - StyledLabel(String(localized: "You completed your first check-in"), .title3, emphasis: .secondary, alignment: .center) + Text(String(localized: "You completed your first check-in")) + .styled(.title3, emphasis: .secondary) + .multilineTextAlignment(.center) } Spacer() @@ -145,7 +149,7 @@ struct FirstCheckInStepView: View { // Continue button if showContinueButton { Button(action: onComplete) { - StyledLabel(String(localized: "Continue to Rituals"), .heading, emphasis: .inverse) + Text(String(localized: "Continue to Rituals")).styled(.heading, emphasis: .inverse) .frame(maxWidth: .infinity) .frame(height: AppMetrics.Size.buttonHeight) .background(AppAccent.primary) @@ -194,7 +198,7 @@ private struct OnboardingHabitRowView: View { SymbolIcon(symbolName, size: .row, color: isCompleted ? AppStatus.success : AppAccent.primary) .frame(width: AppMetrics.Size.iconLarge) - StyledLabel(title, .body, emphasis: .primary) + Text(title).styled(.body, emphasis: .primary) Spacer(minLength: Design.Spacing.medium) diff --git a/Andromida/App/Views/Onboarding/RitualPreviewStepView.swift b/Andromida/App/Views/Onboarding/RitualPreviewStepView.swift index 65081cc..31f755c 100644 --- a/Andromida/App/Views/Onboarding/RitualPreviewStepView.swift +++ b/Andromida/App/Views/Onboarding/RitualPreviewStepView.swift @@ -26,7 +26,9 @@ struct RitualPreviewStepView: View { .frame(height: Design.Spacing.large) // Header - StyledLabel(headerText, .title2Bold, emphasis: .primary, alignment: .center) + Text(headerText) + .styled(.title2Bold, emphasis: .primary) + .multilineTextAlignment(.center) .opacity(animateContent ? 1 : 0) // Ritual preview card @@ -36,9 +38,9 @@ struct RitualPreviewStepView: View { SymbolIcon(preset.iconName, size: .card, color: AppAccent.primary) VStack(alignment: .leading, spacing: Design.Spacing.xSmall) { - StyledLabel(preset.title, .title3Bold, emphasis: .primary) + Text(preset.title).styled(.title3Bold, emphasis: .primary) - StyledLabel(preset.theme, .subheading, emphasis: .secondary) + Text(preset.theme).styled(.subheading, emphasis: .secondary) } } @@ -52,7 +54,7 @@ struct RitualPreviewStepView: View { SymbolIcon(habit.symbolName, size: .inline, color: AppTextColors.secondary) .frame(width: 24) - StyledLabel(habit.title, .body, emphasis: .primary) + Text(habit.title).styled(.body, emphasis: .primary) } } } @@ -62,9 +64,11 @@ struct RitualPreviewStepView: View { // Duration and time HStack(spacing: Design.Spacing.large) { - IconLabel("calendar", String(localized: "\(preset.durationDays) days"), .caption, emphasis: .secondary) + Label(String(localized: "\(preset.durationDays) days"), systemImage: "calendar") + .styled(.caption, emphasis: .secondary) - IconLabel(preset.timeOfDay.symbolName, preset.timeOfDay.displayName, .caption, emphasis: .secondary) + Label(preset.timeOfDay.displayName, systemImage: preset.timeOfDay.symbolName) + .styled(.caption, emphasis: .secondary) } } .padding(Design.Spacing.large) @@ -80,7 +84,7 @@ struct RitualPreviewStepView: View { VStack(spacing: Design.Spacing.medium) { // Primary CTA Button(action: onStartRitual) { - StyledLabel(String(localized: "Start This Ritual"), .heading, emphasis: .inverse) + Text(String(localized: "Start This Ritual")).styled(.heading, emphasis: .inverse) .frame(maxWidth: .infinity) .frame(height: AppMetrics.Size.buttonHeight) .background(AppAccent.primary) @@ -89,7 +93,7 @@ struct RitualPreviewStepView: View { // Skip option Button(action: onSkip) { - StyledLabel(String(localized: "Skip for now"), .subheading, emphasis: .secondary) + Text(String(localized: "Skip for now")).styled(.subheading, emphasis: .secondary) } } .padding(.horizontal, Design.Spacing.xxLarge) diff --git a/Andromida/App/Views/Onboarding/WhatsNextStepView.swift b/Andromida/App/Views/Onboarding/WhatsNextStepView.swift index 157c494..2aebab6 100644 --- a/Andromida/App/Views/Onboarding/WhatsNextStepView.swift +++ b/Andromida/App/Views/Onboarding/WhatsNextStepView.swift @@ -62,7 +62,7 @@ struct WhatsNextStepView: View { // CTA button Button(action: onComplete) { - StyledLabel(String(localized: "Let's Go"), .heading, emphasis: .inverse) + Text(String(localized: "Let's Go")).styled(.heading, emphasis: .inverse) .frame(maxWidth: .infinity) .frame(height: AppMetrics.Size.buttonHeight) .background(AppAccent.primary) @@ -99,9 +99,9 @@ private struct FeatureHelpCard: View { // Text VStack(alignment: .leading, spacing: Design.Spacing.xSmall) { - StyledLabel(title, .heading, emphasis: .primary) + Text(title).styled(.heading, emphasis: .primary) - StyledLabel(description, .caption, emphasis: .secondary) + Text(description).styled(.caption, emphasis: .secondary) } Spacer() diff --git a/Andromida/App/Views/Rituals/Components/HabitPerformanceView.swift b/Andromida/App/Views/Rituals/Components/HabitPerformanceView.swift index b6a3bb3..b9edb90 100644 --- a/Andromida/App/Views/Rituals/Components/HabitPerformanceView.swift +++ b/Andromida/App/Views/Rituals/Components/HabitPerformanceView.swift @@ -29,7 +29,7 @@ struct HabitPerformanceView: View { var body: some View { VStack(alignment: .leading, spacing: Design.Spacing.small) { - StyledLabel(String(localized: "Habit Performance"), .heading, emphasis: .primary) + Text(String(localized: "Habit Performance")).styled(.heading, emphasis: .primary) LazyVGrid(columns: habitColumns, alignment: .leading, spacing: Design.Spacing.xSmall) { ForEach(sortedByRate, id: \.habit.id) { item in @@ -50,11 +50,11 @@ struct HabitPerformanceView: View { SymbolIcon(habit.symbolName, size: .inline, color: colorForRate(rate)) .frame(width: AppMetrics.Size.iconMedium) - StyledLabel(habit.title, .subheading, emphasis: .primary) + Text(habit.title).styled(.subheading, emphasis: .primary) Spacer() - StyledLabel("\(Int(rate * 100))%", .subheadingEmphasis, emphasis: .custom(colorForRate(rate))) + Text("\(Int(rate * 100))%").styled(.subheadingEmphasis, emphasis: .custom(colorForRate(rate))) } // Progress bar diff --git a/Andromida/App/Views/Rituals/Components/RitualCardView.swift b/Andromida/App/Views/Rituals/Components/RitualCardView.swift index 76e614b..3b314b1 100644 --- a/Andromida/App/Views/Rituals/Components/RitualCardView.swift +++ b/Andromida/App/Views/Rituals/Components/RitualCardView.swift @@ -58,7 +58,7 @@ struct RitualCardView: View { .typography(.subheading) .foregroundStyle(hasActiveArc ? AppTextColors.secondary : AppTextColors.tertiary) - StyledLabel(completionSummary, .caption, emphasis: .secondary) + Text(completionSummary).styled(.caption, emphasis: .secondary) } .padding(Design.Spacing.large) .background(AppSurface.card) diff --git a/Andromida/App/Views/Rituals/Components/RitualMilestonesView.swift b/Andromida/App/Views/Rituals/Components/RitualMilestonesView.swift index 47ca859..17d827a 100644 --- a/Andromida/App/Views/Rituals/Components/RitualMilestonesView.swift +++ b/Andromida/App/Views/Rituals/Components/RitualMilestonesView.swift @@ -14,7 +14,7 @@ struct RitualMilestonesView: View { var body: some View { VStack(alignment: .leading, spacing: Design.Spacing.small) { - StyledLabel(String(localized: "Milestones"), .heading, emphasis: .primary) + Text(String(localized: "Milestones")).styled(.heading, emphasis: .primary) HStack(spacing: Design.Spacing.small) { ForEach(milestones) { milestone in @@ -38,9 +38,11 @@ struct RitualMilestonesView: View { SymbolIcon(milestone.symbolName, size: .badge, color: milestone.isAchieved ? AppStatus.success : AppTextColors.tertiary) } - StyledLabel("Day \(milestone.day)", .caption2, emphasis: .custom(milestone.isAchieved ? AppTextColors.primary : AppTextColors.tertiary)) + Text("Day \(milestone.day)").styled(.caption2, emphasis: .custom(milestone.isAchieved ? AppTextColors.primary : AppTextColors.tertiary)) - StyledLabel(milestone.title, .caption2, emphasis: .custom(milestone.isAchieved ? AppTextColors.secondary : AppTextColors.tertiary), lineLimit: 1) + Text(milestone.title) + .styled(.caption2, emphasis: .custom(milestone.isAchieved ? AppTextColors.secondary : AppTextColors.tertiary)) + .lineLimit(1) } .frame(maxWidth: .infinity) .accessibilityElement(children: .combine) diff --git a/Andromida/App/Views/Rituals/Components/RitualProgressStatsView.swift b/Andromida/App/Views/Rituals/Components/RitualProgressStatsView.swift index cf31784..0b9a831 100644 --- a/Andromida/App/Views/Rituals/Components/RitualProgressStatsView.swift +++ b/Andromida/App/Views/Rituals/Components/RitualProgressStatsView.swift @@ -40,7 +40,7 @@ struct RitualProgressStatsView: View { ProgressView(value: progress) .tint(AppAccent.primary) - StyledLabel("\(Int(progress * 100))% complete", .caption, emphasis: .secondary) + Text("\(Int(progress * 100))% complete").styled(.caption, emphasis: .secondary) } } .padding(Design.Spacing.large) @@ -51,12 +51,12 @@ struct RitualProgressStatsView: View { private func statColumn(value: String, secondary: String?, label: String) -> some View { VStack(spacing: Design.Spacing.xSmall) { - StyledLabel(value, .titleBold, emphasis: .primary) + Text(value).styled(.titleBold, emphasis: .primary) // Always show secondary row for consistent height - StyledLabel(secondary ?? " ", .caption, emphasis: .custom(secondary != nil ? AppTextColors.tertiary : .clear)) + Text(secondary ?? " ").styled(.caption, emphasis: .custom(secondary != nil ? AppTextColors.tertiary : .clear)) - StyledLabel(label, .caption2, emphasis: .secondary) + Text(label).styled(.caption2, emphasis: .secondary) } } } diff --git a/Andromida/App/Views/Rituals/RitualDetailView.swift b/Andromida/App/Views/Rituals/RitualDetailView.swift index 5db4108..e33e790 100644 --- a/Andromida/App/Views/Rituals/RitualDetailView.swift +++ b/Andromida/App/Views/Rituals/RitualDetailView.swift @@ -108,7 +108,7 @@ struct RitualDetailView: View { if !ritual.notes.isEmpty { VStack(alignment: .leading, spacing: Design.Spacing.xSmall) { SectionHeaderView(title: String(localized: "Notes")) - StyledLabel(ritual.notes, .body, emphasis: .secondary) + Text(ritual.notes).styled(.body, emphasis: .secondary) } } @@ -257,7 +257,7 @@ struct RitualDetailView: View { VStack(alignment: .leading, spacing: Design.Spacing.medium) { HStack { SymbolIcon("clock.arrow.circlepath", size: .inline, color: AppTextColors.secondary) - StyledLabel(String(localized: "This ritual is not currently active"), .subheading, emphasis: .secondary) + Text(String(localized: "This ritual is not currently active")).styled(.subheading, emphasis: .secondary) } if let lastArc = ritual.latestArc { @@ -266,7 +266,7 @@ struct RitualDetailView: View { let possibleCheckIns = habits.count * lastArc.durationDays 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: .tertiary) + Text(String(localized: "Last arc completed with \(completionRate)% habit completion over \(lastArc.durationDays) days.")).styled(.caption, emphasis: .tertiary) } Button { @@ -312,13 +312,13 @@ struct RitualDetailView: View { HStack(spacing: Design.Spacing.medium) { // Current arc indicator if let arc = ritual.currentArc { - StyledLabel(String(localized: "Arc \(arc.arcNumber)"), .captionEmphasis, emphasis: .custom(AppAccent.primary)) + Text(String(localized: "Arc \(arc.arcNumber)")).styled(.captionEmphasis, emphasis: .custom(AppAccent.primary)) .padding(.horizontal, Design.Spacing.small) .padding(.vertical, Design.Spacing.xSmall) .background(AppAccent.primary.opacity(0.2)) .clipShape(.capsule) } else { - StyledLabel(String(localized: "No active arc"), .caption, emphasis: .tertiary) + Text(String(localized: "No active arc")).styled(.caption, emphasis: .tertiary) .padding(.horizontal, Design.Spacing.small) .padding(.vertical, Design.Spacing.xSmall) .background(AppTextColors.tertiary.opacity(0.2)) @@ -331,7 +331,7 @@ struct RitualDetailView: View { // Category badge (if set) if !ritual.category.isEmpty { let badgeColor = categoryStore.color(for: ritual.category) - StyledLabel(ritual.category, .caption, emphasis: .custom(badgeColor)) + Text(ritual.category).styled(.caption, emphasis: .custom(badgeColor)) .padding(.horizontal, Design.Spacing.small) .padding(.vertical, Design.Spacing.xSmall) .background(badgeColor.opacity(0.15)) @@ -344,9 +344,10 @@ struct RitualDetailView: View { private var timeOfDayBadge: some View { HStack(spacing: 2) { - IconLabel(ritual.timeOfDay.symbolName, ritual.timeOfDay.displayName, .caption2, emphasis: .custom(timeOfDayColor)) - StyledLabel(" : ", .caption2, emphasis: .custom(timeOfDayColor)) - StyledLabel(ritual.timeOfDay.timeRange, .caption2, emphasis: .custom(timeOfDayColor)) + Label(ritual.timeOfDay.displayName, systemImage: ritual.timeOfDay.symbolName) + .styled(.caption2, emphasis: .custom(timeOfDayColor)) + Text(" : ").styled(.caption2, emphasis: .custom(timeOfDayColor)) + Text(ritual.timeOfDay.timeRange).styled(.caption2, emphasis: .custom(timeOfDayColor)) } .padding(.horizontal, Design.Spacing.small) .padding(.vertical, Design.Spacing.xSmall) @@ -381,7 +382,7 @@ struct RitualDetailView: View { ) if completedArcs.isEmpty { - StyledLabel(String(localized: "No completed arcs yet."), .caption, emphasis: .tertiary) + Text(String(localized: "No completed arcs yet.")).styled(.caption, emphasis: .tertiary) } else { LazyVGrid(columns: arcColumns, alignment: .leading, spacing: Design.Spacing.small) { ForEach(completedArcs) { arc in @@ -407,17 +408,17 @@ struct RitualDetailView: View { } label: { HStack { VStack(alignment: .leading, spacing: Design.Spacing.xSmall) { - StyledLabel(String(localized: "Arc \(arc.arcNumber)"), .subheadingEmphasis, emphasis: .primary) + Text(String(localized: "Arc \(arc.arcNumber)")).styled(.subheadingEmphasis, emphasis: .primary) - StyledLabel("\(dateFormatter.string(from: arc.startDate)) – \(dateFormatter.string(from: arc.endDate))", .caption, emphasis: .tertiary) + Text("\(dateFormatter.string(from: arc.startDate)) – \(dateFormatter.string(from: arc.endDate))").styled(.caption, emphasis: .tertiary) } Spacer() VStack(alignment: .trailing, spacing: Design.Spacing.xSmall) { - StyledLabel("\(completionRate)%", .subheadingEmphasis, emphasis: .custom(completionRate >= 70 ? AppStatus.success : AppTextColors.secondary)) + Text("\(completionRate)%").styled(.subheadingEmphasis, emphasis: .custom(completionRate >= 70 ? AppStatus.success : AppTextColors.secondary)) - StyledLabel(String(localized: "\(arc.durationDays) days"), .caption, emphasis: .tertiary) + Text(String(localized: "\(arc.durationDays) days")).styled(.caption, emphasis: .tertiary) } SymbolIcon.chevron(color: AppTextColors.tertiary) @@ -436,13 +437,15 @@ struct RitualDetailView: View { HStack(spacing: Design.Spacing.medium) { // Days remaining if daysRemaining > 0 { - IconLabel("hourglass", String(localized: "\(daysRemaining) days remaining"), .caption, emphasis: .secondary) + Label(String(localized: "\(daysRemaining) days remaining"), systemImage: "hourglass") + .styled(.caption, emphasis: .secondary) .padding(.horizontal, Design.Spacing.medium) .padding(.vertical, Design.Spacing.small) .background(AppSurface.card) .clipShape(.capsule) } else { - IconLabel("checkmark.seal.fill", String(localized: "Arc complete!"), .caption, emphasis: .custom(AppStatus.success)) + Label(String(localized: "Arc complete!"), systemImage: "checkmark.seal.fill") + .styled(.caption, emphasis: .custom(AppStatus.success)) .padding(.horizontal, Design.Spacing.medium) .padding(.vertical, Design.Spacing.small) .background(AppStatus.success.opacity(Design.Opacity.subtle)) @@ -451,7 +454,8 @@ struct RitualDetailView: View { // Ritual streak if ritualStreak > 0 { - IconLabel("flame.fill", String(localized: "\(ritualStreak)-day streak"), .caption, emphasis: .custom(AppStatus.success)) + Label(String(localized: "\(ritualStreak)-day streak"), systemImage: "flame.fill") + .styled(.caption, emphasis: .custom(AppStatus.success)) .padding(.horizontal, Design.Spacing.medium) .padding(.vertical, Design.Spacing.small) .background(AppStatus.success.opacity(Design.Opacity.subtle)) @@ -464,7 +468,8 @@ struct RitualDetailView: View { // Arc comparison (only shown if there's a previous arc) if let comparison = arcComparisonInfo { let comparisonColor = comparison.isAhead ? AppStatus.success : comparison.isBehind ? AppStatus.warning : AppTextColors.secondary - IconLabel(comparison.isAhead ? "arrow.up.right" : comparison.isBehind ? "arrow.down.right" : "equal", comparison.text, .caption, emphasis: .custom(comparisonColor)) + Label(comparison.text, systemImage: comparison.isAhead ? "arrow.up.right" : comparison.isBehind ? "arrow.down.right" : "equal") + .styled(.caption, emphasis: .custom(comparisonColor)) } } } diff --git a/Andromida/App/Views/Rituals/RitualsView.swift b/Andromida/App/Views/Rituals/RitualsView.swift index 09e644a..44f505b 100644 --- a/Andromida/App/Views/Rituals/RitualsView.swift +++ b/Andromida/App/Views/Rituals/RitualsView.swift @@ -141,7 +141,7 @@ struct RitualsView: View { // Time of day header HStack(spacing: Design.Spacing.small) { SymbolIcon(group.timeOfDay.symbolName, size: .inline, color: AppAccent.primary) - StyledLabel(group.timeOfDay.displayName, .subheadingEmphasis, emphasis: .secondary) + Text(group.timeOfDay.displayName).styled(.subheadingEmphasis, emphasis: .secondary) } .padding(.top, Design.Spacing.small) @@ -178,7 +178,7 @@ struct RitualsView: View { VStack(spacing: Design.Spacing.large) { SymbolIcon("sparkles", size: .hero, color: AppAccent.primary) - StyledLabel(String(localized: "No Active Rituals"), .heading, emphasis: .primary) + Text(String(localized: "No Active Rituals")).styled(.heading, emphasis: .primary) Text(String(localized: "Create a custom ritual or browse our preset library to get started.")) .typography(.subheading) @@ -217,7 +217,7 @@ struct RitualsView: View { VStack(spacing: Design.Spacing.large) { SymbolIcon("clock.arrow.circlepath", size: .hero, color: AppTextColors.tertiary) - StyledLabel(String(localized: "No Past Rituals"), .heading, emphasis: .primary) + Text(String(localized: "No Past Rituals")).styled(.heading, emphasis: .primary) Text(String(localized: "Rituals that have ended will appear here. You can restart them anytime.")) .typography(.subheading) @@ -324,12 +324,13 @@ struct RitualsView: View { .clipShape(.rect(cornerRadius: Design.CornerRadius.small)) VStack(alignment: .leading, spacing: Design.Spacing.xSmall) { - StyledLabel(ritual.title, .heading, emphasis: .primary) + Text(ritual.title).styled(.heading, emphasis: .primary) - StyledLabel(ritual.theme, .caption, emphasis: .secondary) + Text(ritual.theme).styled(.caption, emphasis: .secondary) if let lastArc = ritual.latestArc { - IconLabel("calendar", formattedEndDate(lastArc.endDate), .caption2, emphasis: .tertiary) + Label(formattedEndDate(lastArc.endDate), systemImage: "calendar") + .styled(.caption2, emphasis: .tertiary) } } @@ -337,7 +338,7 @@ struct RitualsView: View { // Arc count badge if ritual.completedArcCount > 0 { - StyledLabel("\(ritual.completedArcCount) arc\(ritual.completedArcCount == 1 ? "" : "s")", .caption2, emphasis: .secondary) + Text("\(ritual.completedArcCount) arc\(ritual.completedArcCount == 1 ? "" : "s")").styled(.caption2, emphasis: .secondary) .padding(.horizontal, Design.Spacing.small) .padding(.vertical, Design.Spacing.xSmall) .background(AppSurface.secondary) diff --git a/Andromida/App/Views/Rituals/Sheets/PresetLibrarySheet.swift b/Andromida/App/Views/Rituals/Sheets/PresetLibrarySheet.swift index d94cbe5..d1f4351 100644 --- a/Andromida/App/Views/Rituals/Sheets/PresetLibrarySheet.swift +++ b/Andromida/App/Views/Rituals/Sheets/PresetLibrarySheet.swift @@ -60,7 +60,8 @@ struct PresetLibrarySheet: View { selectedCategory = category } } label: { - IconLabel(category.symbolName, category.displayName, .subheading, emphasis: .custom(selectedCategory == category ? .white : AppTextColors.primary)) + Label(category.displayName, systemImage: category.symbolName) + .styled(.subheading, emphasis: .custom(selectedCategory == category ? .white : AppTextColors.primary)) .padding(.horizontal, Design.Spacing.medium) .padding(.vertical, Design.Spacing.small) .background(selectedCategory == category ? AppAccent.primary : AppSurface.card) @@ -92,14 +93,14 @@ struct PresetLibrarySheet: View { VStack(alignment: .leading, spacing: Design.Spacing.xSmall) { HStack { - StyledLabel(preset.title, .heading, emphasis: .primary) + Text(preset.title).styled(.heading, emphasis: .primary) if isAdded { SymbolIcon("checkmark.circle.fill", size: .badge, color: AppStatus.success) } } - StyledLabel(preset.theme, .subheading, emphasis: .secondary) + Text(preset.theme).styled(.subheading, emphasis: .secondary) } Spacer() @@ -107,7 +108,7 @@ struct PresetLibrarySheet: View { VStack(alignment: .trailing, spacing: Design.Spacing.xSmall) { SymbolIcon(preset.timeOfDay.symbolName, size: .badge, color: AppTextColors.tertiary) - StyledLabel(String(localized: "\(preset.habits.count) habits"), .caption, emphasis: .tertiary) + Text(String(localized: "\(preset.habits.count) habits")).styled(.caption, emphasis: .tertiary) } } @@ -118,7 +119,7 @@ struct PresetLibrarySheet: View { } if preset.habits.count > 4 { - StyledLabel("+\(preset.habits.count - 4)", .caption2, emphasis: .tertiary) + Text("+\(preset.habits.count - 4)").styled(.caption2, emphasis: .tertiary) } } } @@ -197,9 +198,9 @@ struct PresetDetailSheet: View { private var descriptionSection: some View { VStack(alignment: .leading, spacing: Design.Spacing.small) { - StyledLabel(String(localized: "About"), .heading, emphasis: .primary) + Text(String(localized: "About")).styled(.heading, emphasis: .primary) - StyledLabel(preset.notes, .body, emphasis: .secondary) + Text(preset.notes).styled(.body, emphasis: .secondary) } .padding(Design.Spacing.large) .frame(maxWidth: .infinity, alignment: .leading) @@ -209,7 +210,7 @@ struct PresetDetailSheet: View { private var habitsSection: some View { VStack(alignment: .leading, spacing: Design.Spacing.small) { - StyledLabel(String(localized: "Habits"), .heading, emphasis: .primary) + Text(String(localized: "Habits")).styled(.heading, emphasis: .primary) VStack(spacing: Design.Spacing.xSmall) { ForEach(preset.habits) { habit in @@ -217,7 +218,7 @@ struct PresetDetailSheet: View { SymbolIcon(habit.symbolName, size: .inline, color: AppAccent.primary) .frame(width: 24) - StyledLabel(habit.title, .subheading, emphasis: .primary) + Text(habit.title).styled(.subheading, emphasis: .primary) Spacer() } @@ -241,12 +242,11 @@ struct PresetDetailSheet: View { store.createRitualFromPreset(preset) hasBeenAdded = true } label: { - IconLabel( - isAlreadyAdded || hasBeenAdded ? "checkmark.circle.fill" : "plus.circle.fill", + Label( isAlreadyAdded || hasBeenAdded ? String(localized: "Added to My Rituals") : String(localized: "Add to My Rituals"), - .heading, - emphasis: .custom(.white) + systemImage: isAlreadyAdded || hasBeenAdded ? "checkmark.circle.fill" : "plus.circle.fill" ) + .styled(.heading, emphasis: .custom(.white)) .frame(maxWidth: .infinity) .padding(Design.Spacing.medium) .background(isAlreadyAdded || hasBeenAdded ? AppStatus.success : AppAccent.primary) diff --git a/Andromida/App/Views/Rituals/Sheets/RitualEditSheet.swift b/Andromida/App/Views/Rituals/Sheets/RitualEditSheet.swift index bf8a508..42d3aa4 100644 --- a/Andromida/App/Views/Rituals/Sheets/RitualEditSheet.swift +++ b/Andromida/App/Views/Rituals/Sheets/RitualEditSheet.swift @@ -122,7 +122,7 @@ struct RitualEditSheet: View { // Category selection - simple picker from CategoryStore VStack(alignment: .leading, spacing: Design.Spacing.medium) { - StyledLabel(String(localized: "Category"), .subheading, emphasis: .secondary) + Text(String(localized: "Category")).styled(.subheading, emphasis: .secondary) // Horizontal scrollable category chips ScrollView(.horizontal, showsIndicators: false) { @@ -169,7 +169,8 @@ struct RitualEditSheet: View { } // Show the time range for the selected time of day - IconLabel(timeOfDay.symbolName, timeOfDay.timeRange, .caption, emphasis: .tertiary) + Label(timeOfDay.timeRange, systemImage: timeOfDay.symbolName) + .styled(.caption, emphasis: .tertiary) } .listRowBackground(AppSurface.card) @@ -225,7 +226,7 @@ struct RitualEditSheet: View { Button { durationDays = Double(days) } label: { - StyledLabel("\(days)", .caption, emphasis: .custom(Int(durationDays) == days ? AppAccent.primary : AppTextColors.tertiary)) + Text("\(days)").styled(.caption, emphasis: .custom(Int(durationDays) == days ? AppAccent.primary : AppTextColors.tertiary)) .padding(.horizontal, Design.Spacing.small) .padding(.vertical, Design.Spacing.xSmall) .background(Int(durationDays) == days ? AppAccent.primary.opacity(0.2) : AppSurface.secondary) @@ -241,7 +242,7 @@ struct RitualEditSheet: View { } header: { Text(String(localized: "Schedule")) } footer: { - StyledLabel(String(localized: "Tap the duration to enter a custom number of days (up to 365)."), .caption, emphasis: .secondary) + Text(String(localized: "Tap the duration to enter a custom number of days (up to 365).")).styled(.caption, emphasis: .secondary) } } @@ -314,11 +315,11 @@ struct RitualEditSheet: View { HStack { Text(String(localized: "Habits")) Spacer() - StyledLabel(String(localized: "\(habits.count) habits"), .caption, emphasis: .tertiary) + Text(String(localized: "\(habits.count) habits")).styled(.caption, emphasis: .tertiary) } } footer: { if habits.count > 1 { - StyledLabel(String(localized: "Drag the handle to reorder habits."), .caption, emphasis: .secondary) + Text(String(localized: "Drag the handle to reorder habits.")).styled(.caption, emphasis: .secondary) } } } @@ -377,7 +378,7 @@ struct RitualEditSheet: View { .fill(color) .frame(width: 10, height: 10) } - StyledLabel(label, .subheading, emphasis: .custom(isSelected ? .white : AppTextColors.primary)) + Text(label).styled(.subheading, emphasis: .custom(isSelected ? .white : AppTextColors.primary)) } .padding(.horizontal, Design.Spacing.medium) .padding(.vertical, Design.Spacing.small) @@ -493,7 +494,7 @@ struct IconPickerSheet: View { LazyVStack(alignment: .leading, spacing: Design.Spacing.large) { ForEach(iconGroups, id: \.name) { group in VStack(alignment: .leading, spacing: Design.Spacing.small) { - StyledLabel(group.name, .caption, emphasis: .secondary) + Text(group.name).styled(.caption, emphasis: .secondary) .padding(.horizontal, Design.Spacing.small) LazyVGrid(columns: Array(repeating: GridItem(.flexible()), count: 6), spacing: Design.Spacing.small) { @@ -597,7 +598,7 @@ struct HabitIconPickerSheet: View { LazyVStack(alignment: .leading, spacing: Design.Spacing.large) { ForEach(iconGroups, id: \.name) { group in VStack(alignment: .leading, spacing: Design.Spacing.small) { - StyledLabel(group.name, .caption, emphasis: .secondary) + Text(group.name).styled(.caption, emphasis: .secondary) .padding(.horizontal, Design.Spacing.small) LazyVGrid(columns: Array(repeating: GridItem(.flexible()), count: 6), spacing: Design.Spacing.small) { diff --git a/Andromida/App/Views/Today/Components/RitualFocusCardView.swift b/Andromida/App/Views/Today/Components/RitualFocusCardView.swift index e5fde09..f2b73d1 100644 --- a/Andromida/App/Views/Today/Components/RitualFocusCardView.swift +++ b/Andromida/App/Views/Today/Components/RitualFocusCardView.swift @@ -33,7 +33,7 @@ struct RitualFocusCardView: View { .accessibilityHidden(true) // Title - StyledLabel(title, .heading, emphasis: .primary) + Text(title).styled(.heading, emphasis: .primary) Spacer(minLength: Design.Spacing.medium) @@ -48,12 +48,12 @@ struct RitualFocusCardView: View { .accessibilityLabel(Text(dayLabel)) } - StyledLabel(theme, .subheading, emphasis: .secondary) + Text(theme).styled(.subheading, emphasis: .secondary) VStack(alignment: .leading, spacing: Design.Spacing.xSmall) { ProgressView(value: progress) .tint(AppAccent.primary) - StyledLabel(completionSummary, .caption, emphasis: .secondary) + Text(completionSummary).styled(.caption, emphasis: .secondary) } } .padding(Design.Spacing.large) diff --git a/Andromida/App/Views/Today/Components/TodayHabitRowView.swift b/Andromida/App/Views/Today/Components/TodayHabitRowView.swift index 218ce55..528d1ce 100644 --- a/Andromida/App/Views/Today/Components/TodayHabitRowView.swift +++ b/Andromida/App/Views/Today/Components/TodayHabitRowView.swift @@ -29,7 +29,7 @@ struct TodayHabitRowView: View { .frame(width: AppMetrics.Size.iconLarge) .accessibilityHidden(true) - StyledLabel(title, .subheading, emphasis: .primary) + Text(title).styled(.subheading, emphasis: .primary) Spacer(minLength: Design.Spacing.medium) diff --git a/Andromida/App/Views/Today/Components/TodayHeaderView.swift b/Andromida/App/Views/Today/Components/TodayHeaderView.swift index 58bfc2c..ad31a48 100644 --- a/Andromida/App/Views/Today/Components/TodayHeaderView.swift +++ b/Andromida/App/Views/Today/Components/TodayHeaderView.swift @@ -10,8 +10,8 @@ struct TodayHeaderView: View { var body: some View { VStack(alignment: .leading, spacing: Design.Spacing.xxxSmall) { - StyledLabel(String(localized: "Today"), .heroBold, emphasis: .primary) - StyledLabel(dateText, .subheading, emphasis: .secondary) + Text(String(localized: "Today")).styled(.heroBold, emphasis: .primary) + Text(dateText).styled(.subheading, emphasis: .secondary) } .frame(maxWidth: .infinity, alignment: .leading) .accessibilityElement(children: .combine)