Signed-off-by: Matt Bruce <mbrucedogs@gmail.com>
This commit is contained in:
parent
23b9c90871
commit
76dda638cc
@ -21,16 +21,17 @@ 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) {
|
||||||
Text(title)
|
TitleLabel(title, style: .displaySmall, color: AppTextColors.primary)
|
||||||
.font(.title3)
|
|
||||||
.foregroundStyle(AppTextColors.primary)
|
// Exception: Uses .bodyLarge which isn't a standard BodyLabel weight
|
||||||
.bold()
|
|
||||||
Text(message)
|
Text(message)
|
||||||
.font(.body)
|
.font(Design.Typography.bodyLarge)
|
||||||
.foregroundStyle(AppTextColors.secondary)
|
.foregroundStyle(AppTextColors.secondary)
|
||||||
|
|
||||||
Button(action: action) {
|
Button(action: action) {
|
||||||
|
// Exception: Needs .frame() modifiers
|
||||||
Text(actionTitle)
|
Text(actionTitle)
|
||||||
.font(.headline)
|
.font(Design.Typography.headline)
|
||||||
.foregroundStyle(AppTextColors.primary)
|
.foregroundStyle(AppTextColors.primary)
|
||||||
.frame(maxWidth: .infinity)
|
.frame(maxWidth: .infinity)
|
||||||
.frame(height: AppMetrics.Size.buttonHeight)
|
.frame(height: AppMetrics.Size.buttonHeight)
|
||||||
|
|||||||
@ -12,13 +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) {
|
||||||
Text(title)
|
TitleLabel(title, style: .headline, color: AppTextColors.primary)
|
||||||
.font(.headline)
|
|
||||||
.foregroundStyle(AppTextColors.primary)
|
|
||||||
if let subtitle {
|
if let subtitle {
|
||||||
Text(subtitle)
|
BodyLabel(subtitle, emphasis: .secondary, color: AppTextColors.secondary)
|
||||||
.font(.subheadline)
|
|
||||||
.foregroundStyle(AppTextColors.secondary)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.frame(maxWidth: .infinity, alignment: .leading)
|
.frame(maxWidth: .infinity, alignment: .leading)
|
||||||
|
|||||||
@ -22,31 +22,21 @@ 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 {
|
||||||
Text(card.title)
|
BodyLabel(card.title, weight: .bold, color: AppTextColors.secondary)
|
||||||
.font(.subheadline)
|
|
||||||
.bold()
|
|
||||||
.foregroundStyle(AppTextColors.secondary)
|
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
|
|
||||||
// Subtle tap affordance
|
// Subtle tap affordance
|
||||||
Image(systemName: "chevron.right")
|
SymbolIcon.chevron(color: AppTextColors.tertiary)
|
||||||
.font(.caption2)
|
|
||||||
.foregroundStyle(AppTextColors.tertiary)
|
|
||||||
.accessibilityHidden(true)
|
.accessibilityHidden(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show value prominently
|
// Show value prominently
|
||||||
Text(card.value)
|
TitleLabel(card.value, style: .displayMedium, color: AppTextColors.primary)
|
||||||
.font(.title)
|
|
||||||
.foregroundStyle(AppTextColors.primary)
|
|
||||||
.bold()
|
|
||||||
|
|
||||||
// Show caption if present (non-chart cards)
|
// Show caption if present (non-chart cards)
|
||||||
if !card.caption.isEmpty {
|
if !card.caption.isEmpty {
|
||||||
Text(card.caption)
|
CaptionLabel(card.caption, color: AppTextColors.secondary)
|
||||||
.font(.caption)
|
|
||||||
.foregroundStyle(AppTextColors.secondary)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show full-width mini bar chart at bottom (Athlytic style)
|
// Show full-width mini bar chart at bottom (Athlytic style)
|
||||||
|
|||||||
@ -81,17 +81,15 @@ struct InsightDetailSheet: View {
|
|||||||
|
|
||||||
private var headerSection: some View {
|
private var headerSection: some View {
|
||||||
VStack(spacing: Design.Spacing.medium) {
|
VStack(spacing: Design.Spacing.medium) {
|
||||||
Image(systemName: card.symbolName)
|
SymbolIcon(card.symbolName, size: .hero, color: AppAccent.primary)
|
||||||
.font(.system(size: Design.IconSize.hero))
|
|
||||||
.foregroundStyle(AppAccent.primary)
|
|
||||||
.accessibilityHidden(true)
|
.accessibilityHidden(true)
|
||||||
|
|
||||||
Text(card.value)
|
Text(card.value)
|
||||||
.font(.system(size: Design.IconSize.hero, weight: .bold))
|
.font(.system(size: Design.SymbolSize.hero, weight: .bold))
|
||||||
.foregroundStyle(AppTextColors.primary)
|
.foregroundStyle(AppTextColors.primary)
|
||||||
|
|
||||||
Text(card.caption)
|
Text(card.caption)
|
||||||
.font(.subheadline)
|
.font(Design.Typography.body)
|
||||||
.foregroundStyle(AppTextColors.secondary)
|
.foregroundStyle(AppTextColors.secondary)
|
||||||
}
|
}
|
||||||
.frame(maxWidth: .infinity)
|
.frame(maxWidth: .infinity)
|
||||||
|
|||||||
@ -146,9 +146,7 @@ struct FirstCheckInStepView: View {
|
|||||||
Spacer()
|
Spacer()
|
||||||
|
|
||||||
// Success icon
|
// Success icon
|
||||||
Image(systemName: "checkmark.circle.fill")
|
SymbolIcon("checkmark.circle.fill", size: .hero, color: AppStatus.success)
|
||||||
.font(.system(size: Design.IconSize.hero))
|
|
||||||
.foregroundStyle(AppStatus.success)
|
|
||||||
.scaleEffect(showCelebration ? 1 : 0.5)
|
.scaleEffect(showCelebration ? 1 : 0.5)
|
||||||
.opacity(showCelebration ? 1 : 0)
|
.opacity(showCelebration ? 1 : 0)
|
||||||
|
|
||||||
|
|||||||
@ -21,8 +21,7 @@ struct GoalSelectionStepView: View {
|
|||||||
// Header
|
// Header
|
||||||
VStack(spacing: Design.Spacing.small) {
|
VStack(spacing: Design.Spacing.small) {
|
||||||
Text(String(localized: "What would you like to focus on?"))
|
Text(String(localized: "What would you like to focus on?"))
|
||||||
.font(.title2)
|
.font(Design.Typography.displaySmall)
|
||||||
.fontWeight(.bold)
|
|
||||||
.foregroundStyle(AppTextColors.primary)
|
.foregroundStyle(AppTextColors.primary)
|
||||||
.multilineTextAlignment(.center)
|
.multilineTextAlignment(.center)
|
||||||
}
|
}
|
||||||
@ -56,7 +55,7 @@ struct GoalSelectionStepView: View {
|
|||||||
if !selectedGoals.isEmpty {
|
if !selectedGoals.isEmpty {
|
||||||
Button(action: onContinue) {
|
Button(action: onContinue) {
|
||||||
Text(String(localized: "Continue"))
|
Text(String(localized: "Continue"))
|
||||||
.font(.headline)
|
.font(Design.Typography.headline)
|
||||||
.foregroundStyle(AppTextColors.inverse)
|
.foregroundStyle(AppTextColors.inverse)
|
||||||
.frame(maxWidth: .infinity)
|
.frame(maxWidth: .infinity)
|
||||||
.frame(height: AppMetrics.Size.buttonHeight)
|
.frame(height: AppMetrics.Size.buttonHeight)
|
||||||
@ -95,18 +94,16 @@ private struct GoalCardView: View {
|
|||||||
Button(action: onTap) {
|
Button(action: onTap) {
|
||||||
VStack(spacing: Design.Spacing.medium) {
|
VStack(spacing: Design.Spacing.medium) {
|
||||||
// Icon
|
// Icon
|
||||||
Image(systemName: goal.symbolName)
|
SymbolIcon(goal.symbolName, size: .card, color: isSelected ? AppAccent.primary : AppTextColors.secondary)
|
||||||
.font(.system(size: Design.IconSize.xxLarge))
|
|
||||||
.foregroundStyle(isSelected ? AppAccent.primary : AppTextColors.secondary)
|
|
||||||
|
|
||||||
// Text
|
// Text
|
||||||
VStack(spacing: Design.Spacing.xSmall) {
|
VStack(spacing: Design.Spacing.xSmall) {
|
||||||
Text(goal.displayName)
|
Text(goal.displayName)
|
||||||
.font(.headline)
|
.font(Design.Typography.headline)
|
||||||
.foregroundStyle(AppTextColors.primary)
|
.foregroundStyle(AppTextColors.primary)
|
||||||
|
|
||||||
Text(goal.subtitle)
|
Text(goal.subtitle)
|
||||||
.font(.caption)
|
.font(Design.Typography.caption)
|
||||||
.foregroundStyle(AppTextColors.secondary)
|
.foregroundStyle(AppTextColors.secondary)
|
||||||
.multilineTextAlignment(.center)
|
.multilineTextAlignment(.center)
|
||||||
.lineLimit(2)
|
.lineLimit(2)
|
||||||
|
|||||||
@ -16,8 +16,7 @@ struct TimeSelectionStepView: View {
|
|||||||
// Header
|
// Header
|
||||||
VStack(spacing: Design.Spacing.small) {
|
VStack(spacing: Design.Spacing.small) {
|
||||||
Text(String(localized: "When do you want to build habits?"))
|
Text(String(localized: "When do you want to build habits?"))
|
||||||
.font(.title2)
|
.font(Design.Typography.displaySmall)
|
||||||
.fontWeight(.bold)
|
|
||||||
.foregroundStyle(AppTextColors.primary)
|
.foregroundStyle(AppTextColors.primary)
|
||||||
.multilineTextAlignment(.center)
|
.multilineTextAlignment(.center)
|
||||||
}
|
}
|
||||||
@ -51,7 +50,7 @@ struct TimeSelectionStepView: View {
|
|||||||
if selectedTime != nil {
|
if selectedTime != nil {
|
||||||
Button(action: onContinue) {
|
Button(action: onContinue) {
|
||||||
Text(String(localized: "Continue"))
|
Text(String(localized: "Continue"))
|
||||||
.font(.headline)
|
.font(Design.Typography.headline)
|
||||||
.foregroundStyle(AppTextColors.inverse)
|
.foregroundStyle(AppTextColors.inverse)
|
||||||
.frame(maxWidth: .infinity)
|
.frame(maxWidth: .infinity)
|
||||||
.frame(height: AppMetrics.Size.buttonHeight)
|
.frame(height: AppMetrics.Size.buttonHeight)
|
||||||
@ -82,19 +81,17 @@ private struct TimeCardView: View {
|
|||||||
Button(action: onTap) {
|
Button(action: onTap) {
|
||||||
HStack(spacing: Design.Spacing.medium) {
|
HStack(spacing: Design.Spacing.medium) {
|
||||||
// Icon
|
// Icon
|
||||||
Image(systemName: time.symbolName)
|
SymbolIcon(time.symbolName, size: .rowContainer, color: isSelected ? AppAccent.primary : AppTextColors.secondary)
|
||||||
.font(.system(size: Design.IconSize.xLarge))
|
.frame(width: Design.Size.actionRowMinHeight)
|
||||||
.foregroundStyle(isSelected ? AppAccent.primary : AppTextColors.secondary)
|
|
||||||
.frame(width: 44)
|
|
||||||
|
|
||||||
// Text
|
// Text
|
||||||
VStack(alignment: .leading, spacing: Design.Spacing.xSmall) {
|
VStack(alignment: .leading, spacing: Design.Spacing.xSmall) {
|
||||||
Text(time.displayName)
|
Text(time.displayName)
|
||||||
.font(.headline)
|
.font(Design.Typography.headline)
|
||||||
.foregroundStyle(AppTextColors.primary)
|
.foregroundStyle(AppTextColors.primary)
|
||||||
|
|
||||||
Text(time.subtitle)
|
Text(time.subtitle)
|
||||||
.font(.subheadline)
|
.font(Design.Typography.body)
|
||||||
.foregroundStyle(AppTextColors.secondary)
|
.foregroundStyle(AppTextColors.secondary)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,9 +99,7 @@ private struct TimeCardView: View {
|
|||||||
|
|
||||||
// Selection indicator
|
// Selection indicator
|
||||||
if isSelected {
|
if isSelected {
|
||||||
Image(systemName: "checkmark.circle.fill")
|
SymbolIcon("checkmark.circle.fill", size: .rowContainer, color: AppAccent.primary)
|
||||||
.font(.title2)
|
|
||||||
.foregroundStyle(AppAccent.primary)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.padding(Design.Spacing.large)
|
.padding(Design.Spacing.large)
|
||||||
|
|||||||
@ -21,13 +21,12 @@ struct WelcomeStepView: View {
|
|||||||
|
|
||||||
VStack(spacing: Design.Spacing.medium) {
|
VStack(spacing: Design.Spacing.medium) {
|
||||||
Text(String(localized: "Welcome to Rituals"))
|
Text(String(localized: "Welcome to Rituals"))
|
||||||
.font(.largeTitle)
|
.font(Design.Typography.displayLarge)
|
||||||
.fontWeight(.bold)
|
|
||||||
.foregroundStyle(AppTextColors.primary)
|
.foregroundStyle(AppTextColors.primary)
|
||||||
.multilineTextAlignment(.center)
|
.multilineTextAlignment(.center)
|
||||||
|
|
||||||
Text(String(localized: "Build lasting habits through focused, time-bound journeys"))
|
Text(String(localized: "Build lasting habits through focused, time-bound journeys"))
|
||||||
.font(.title3)
|
.font(Design.Typography.bodyLarge)
|
||||||
.foregroundStyle(AppTextColors.secondary)
|
.foregroundStyle(AppTextColors.secondary)
|
||||||
.multilineTextAlignment(.center)
|
.multilineTextAlignment(.center)
|
||||||
.padding(.horizontal, Design.Spacing.xxLarge)
|
.padding(.horizontal, Design.Spacing.xxLarge)
|
||||||
@ -40,7 +39,7 @@ struct WelcomeStepView: View {
|
|||||||
// Get Started button
|
// Get Started button
|
||||||
Button(action: onContinue) {
|
Button(action: onContinue) {
|
||||||
Text(String(localized: "Get Started"))
|
Text(String(localized: "Get Started"))
|
||||||
.font(.headline)
|
.font(Design.Typography.headline)
|
||||||
.foregroundStyle(AppTextColors.inverse)
|
.foregroundStyle(AppTextColors.inverse)
|
||||||
.frame(maxWidth: .infinity)
|
.frame(maxWidth: .infinity)
|
||||||
.frame(height: AppMetrics.Size.buttonHeight)
|
.frame(height: AppMetrics.Size.buttonHeight)
|
||||||
@ -105,9 +104,7 @@ struct WelcomeStepView: View {
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Center icon
|
// Center icon
|
||||||
Image(systemName: "sparkles")
|
SymbolIcon("sparkles", size: .card, color: AppAccent.primary)
|
||||||
.font(.system(size: Design.IconSize.xxLarge))
|
|
||||||
.foregroundStyle(AppAccent.primary)
|
|
||||||
.scaleEffect(animateRings ? 1.1 : 1.0)
|
.scaleEffect(animateRings ? 1.1 : 1.0)
|
||||||
.animation(
|
.animation(
|
||||||
.easeInOut(duration: 1.5).repeatForever(autoreverses: true),
|
.easeInOut(duration: 1.5).repeatForever(autoreverses: true),
|
||||||
|
|||||||
@ -13,17 +13,14 @@ struct WhatsNextStepView: View {
|
|||||||
|
|
||||||
// Header
|
// Header
|
||||||
VStack(spacing: Design.Spacing.medium) {
|
VStack(spacing: Design.Spacing.medium) {
|
||||||
Image(systemName: "checkmark.circle.fill")
|
SymbolIcon("checkmark.circle.fill", size: .section, color: AppStatus.success)
|
||||||
.font(.system(size: Design.IconSize.display))
|
|
||||||
.foregroundStyle(AppStatus.success)
|
|
||||||
|
|
||||||
Text(String(localized: "You're all set!"))
|
Text(String(localized: "You're all set!"))
|
||||||
.font(.largeTitle)
|
.font(Design.Typography.displayLarge)
|
||||||
.fontWeight(.bold)
|
|
||||||
.foregroundStyle(AppTextColors.primary)
|
.foregroundStyle(AppTextColors.primary)
|
||||||
|
|
||||||
Text(String(localized: "Here's how to get the most from Rituals"))
|
Text(String(localized: "Here's how to get the most from Rituals"))
|
||||||
.font(.subheadline)
|
.font(Design.Typography.body)
|
||||||
.foregroundStyle(AppTextColors.secondary)
|
.foregroundStyle(AppTextColors.secondary)
|
||||||
.multilineTextAlignment(.center)
|
.multilineTextAlignment(.center)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -32,20 +32,19 @@ struct RitualCardView: View {
|
|||||||
VStack(alignment: .leading, spacing: Design.Spacing.medium) {
|
VStack(alignment: .leading, spacing: Design.Spacing.medium) {
|
||||||
HStack(spacing: Design.Spacing.small) {
|
HStack(spacing: Design.Spacing.small) {
|
||||||
// Icon
|
// Icon
|
||||||
Image(systemName: iconName)
|
SymbolIcon(iconName, size: .row, color: hasActiveArc ? AppAccent.primary : AppTextColors.tertiary)
|
||||||
.foregroundStyle(hasActiveArc ? AppAccent.primary : AppTextColors.tertiary)
|
|
||||||
.accessibilityHidden(true)
|
.accessibilityHidden(true)
|
||||||
|
|
||||||
// Title
|
// Title
|
||||||
Text(title)
|
Text(title)
|
||||||
.font(.headline)
|
.font(Design.Typography.headline)
|
||||||
.foregroundStyle(hasActiveArc ? AppTextColors.primary : AppTextColors.tertiary)
|
.foregroundStyle(hasActiveArc ? AppTextColors.primary : AppTextColors.tertiary)
|
||||||
|
|
||||||
Spacer(minLength: Design.Spacing.medium)
|
Spacer(minLength: Design.Spacing.medium)
|
||||||
|
|
||||||
// Day label
|
// Day label
|
||||||
Text(dayLabel)
|
Text(dayLabel)
|
||||||
.font(.caption)
|
.font(Design.Typography.caption)
|
||||||
.foregroundStyle(AppTextColors.secondary)
|
.foregroundStyle(AppTextColors.secondary)
|
||||||
.padding(.horizontal, Design.Spacing.small)
|
.padding(.horizontal, Design.Spacing.small)
|
||||||
.padding(.vertical, Design.Spacing.xxxSmall)
|
.padding(.vertical, Design.Spacing.xxxSmall)
|
||||||
@ -55,11 +54,11 @@ struct RitualCardView: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Text(theme)
|
Text(theme)
|
||||||
.font(.subheadline)
|
.font(Design.Typography.body)
|
||||||
.foregroundStyle(hasActiveArc ? AppTextColors.secondary : AppTextColors.tertiary)
|
.foregroundStyle(hasActiveArc ? AppTextColors.secondary : AppTextColors.tertiary)
|
||||||
|
|
||||||
Text(completionSummary)
|
Text(completionSummary)
|
||||||
.font(.caption)
|
.font(Design.Typography.caption)
|
||||||
.foregroundStyle(AppTextColors.secondary)
|
.foregroundStyle(AppTextColors.secondary)
|
||||||
}
|
}
|
||||||
.padding(Design.Spacing.large)
|
.padding(Design.Spacing.large)
|
||||||
|
|||||||
@ -199,20 +199,17 @@ struct RitualDetailView: View {
|
|||||||
|
|
||||||
private var headerSection: some View {
|
private var headerSection: some View {
|
||||||
HStack(spacing: Design.Spacing.medium) {
|
HStack(spacing: Design.Spacing.medium) {
|
||||||
Image(systemName: ritual.iconName)
|
SymbolIcon(ritual.iconName, size: .rowContainer, color: ritual.hasActiveArc ? AppAccent.primary : AppTextColors.secondary)
|
||||||
.font(.system(size: Design.IconSize.xLarge))
|
.frame(width: Design.Size.iconContainerLarge, height: Design.Size.iconContainerLarge)
|
||||||
.foregroundStyle(ritual.hasActiveArc ? AppAccent.primary : AppTextColors.secondary)
|
|
||||||
.frame(width: 56, height: 56)
|
|
||||||
.background((ritual.hasActiveArc ? AppAccent.primary : AppTextColors.secondary).opacity(0.1))
|
.background((ritual.hasActiveArc ? AppAccent.primary : AppTextColors.secondary).opacity(0.1))
|
||||||
.clipShape(.rect(cornerRadius: Design.CornerRadius.large))
|
.clipShape(.rect(cornerRadius: Design.CornerRadius.large))
|
||||||
|
|
||||||
VStack(alignment: .leading, spacing: Design.Spacing.xSmall) {
|
VStack(alignment: .leading, spacing: Design.Spacing.xSmall) {
|
||||||
Text(ritual.title)
|
Text(ritual.title)
|
||||||
.font(.title2)
|
.font(Design.Typography.displaySmall)
|
||||||
.foregroundStyle(AppTextColors.primary)
|
.foregroundStyle(AppTextColors.primary)
|
||||||
.bold()
|
|
||||||
Text(ritual.theme)
|
Text(ritual.theme)
|
||||||
.font(.subheadline)
|
.font(Design.Typography.body)
|
||||||
.foregroundStyle(AppTextColors.secondary)
|
.foregroundStyle(AppTextColors.secondary)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -180,16 +180,14 @@ struct RitualsView: View {
|
|||||||
|
|
||||||
private var currentEmptyState: some View {
|
private var currentEmptyState: some View {
|
||||||
VStack(spacing: Design.Spacing.large) {
|
VStack(spacing: Design.Spacing.large) {
|
||||||
Image(systemName: "sparkles")
|
SymbolIcon("sparkles", size: .hero, color: AppAccent.primary)
|
||||||
.font(.system(size: Design.IconSize.hero))
|
|
||||||
.foregroundStyle(AppAccent.primary)
|
|
||||||
|
|
||||||
Text(String(localized: "No Active Rituals"))
|
Text(String(localized: "No Active Rituals"))
|
||||||
.font(.headline)
|
.font(Design.Typography.headline)
|
||||||
.foregroundStyle(AppTextColors.primary)
|
.foregroundStyle(AppTextColors.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."))
|
||||||
.font(.subheadline)
|
.font(Design.Typography.body)
|
||||||
.foregroundStyle(AppTextColors.secondary)
|
.foregroundStyle(AppTextColors.secondary)
|
||||||
.multilineTextAlignment(.center)
|
.multilineTextAlignment(.center)
|
||||||
|
|
||||||
@ -212,7 +210,7 @@ struct RitualsView: View {
|
|||||||
|
|
||||||
if !store.pastRituals.isEmpty {
|
if !store.pastRituals.isEmpty {
|
||||||
Text(String(localized: "Or restart a past ritual from the Past tab."))
|
Text(String(localized: "Or restart a past ritual from the Past tab."))
|
||||||
.font(.caption)
|
.font(Design.Typography.caption)
|
||||||
.foregroundStyle(AppTextColors.tertiary)
|
.foregroundStyle(AppTextColors.tertiary)
|
||||||
.padding(.top, Design.Spacing.small)
|
.padding(.top, Design.Spacing.small)
|
||||||
}
|
}
|
||||||
@ -223,16 +221,14 @@ struct RitualsView: View {
|
|||||||
|
|
||||||
private var pastEmptyState: some View {
|
private var pastEmptyState: some View {
|
||||||
VStack(spacing: Design.Spacing.large) {
|
VStack(spacing: Design.Spacing.large) {
|
||||||
Image(systemName: "clock.arrow.circlepath")
|
SymbolIcon("clock.arrow.circlepath", size: .hero, color: AppTextColors.tertiary)
|
||||||
.font(.system(size: Design.IconSize.hero))
|
|
||||||
.foregroundStyle(AppTextColors.tertiary)
|
|
||||||
|
|
||||||
Text(String(localized: "No Past Rituals"))
|
Text(String(localized: "No Past Rituals"))
|
||||||
.font(.headline)
|
.font(Design.Typography.headline)
|
||||||
.foregroundStyle(AppTextColors.primary)
|
.foregroundStyle(AppTextColors.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."))
|
||||||
.font(.subheadline)
|
.font(Design.Typography.body)
|
||||||
.foregroundStyle(AppTextColors.secondary)
|
.foregroundStyle(AppTextColors.secondary)
|
||||||
.multilineTextAlignment(.center)
|
.multilineTextAlignment(.center)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -63,17 +63,15 @@ struct ArcRenewalSheet: View {
|
|||||||
|
|
||||||
private var celebrationHeader: some View {
|
private var celebrationHeader: some View {
|
||||||
VStack(spacing: Design.Spacing.medium) {
|
VStack(spacing: Design.Spacing.medium) {
|
||||||
Image(systemName: "checkmark.seal.fill")
|
SymbolIcon("checkmark.seal.fill", size: .section, color: AppStatus.success)
|
||||||
.font(.system(size: Design.IconSize.display))
|
|
||||||
.foregroundStyle(AppStatus.success)
|
|
||||||
|
|
||||||
Text(ritual.title)
|
Text(ritual.title)
|
||||||
.font(.title2.bold())
|
.font(Design.Typography.displaySmall)
|
||||||
.foregroundStyle(AppTextColors.primary)
|
.foregroundStyle(AppTextColors.primary)
|
||||||
|
|
||||||
if let arc = completedArc {
|
if let arc = completedArc {
|
||||||
Text(String(localized: "Arc \(arc.arcNumber) Complete"))
|
Text(String(localized: "Arc \(arc.arcNumber) Complete"))
|
||||||
.font(.subheadline)
|
.font(Design.Typography.body)
|
||||||
.foregroundStyle(AppTextColors.secondary)
|
.foregroundStyle(AppTextColors.secondary)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -84,26 +82,24 @@ struct ArcRenewalSheet: View {
|
|||||||
private var summaryCard: some View {
|
private var summaryCard: some View {
|
||||||
VStack(alignment: .leading, spacing: Design.Spacing.medium) {
|
VStack(alignment: .leading, spacing: Design.Spacing.medium) {
|
||||||
Text(String(localized: "Your Journey"))
|
Text(String(localized: "Your Journey"))
|
||||||
.font(.headline)
|
.font(Design.Typography.headline)
|
||||||
.foregroundStyle(AppTextColors.primary)
|
.foregroundStyle(AppTextColors.primary)
|
||||||
|
|
||||||
HStack {
|
HStack {
|
||||||
Image(systemName: "chart.line.uptrend.xyaxis")
|
SymbolIcon("chart.line.uptrend.xyaxis", size: .row, color: AppAccent.primary)
|
||||||
.foregroundStyle(AppAccent.primary)
|
|
||||||
Text(arcSummary)
|
Text(arcSummary)
|
||||||
|
.font(Design.Typography.body)
|
||||||
.foregroundStyle(AppTextColors.secondary)
|
.foregroundStyle(AppTextColors.secondary)
|
||||||
}
|
}
|
||||||
.font(.subheadline)
|
|
||||||
|
|
||||||
if let arc = completedArc {
|
if let arc = completedArc {
|
||||||
let habitCount = (arc.habits ?? []).count
|
let habitCount = (arc.habits ?? []).count
|
||||||
HStack {
|
HStack {
|
||||||
Image(systemName: "checkmark.circle.fill")
|
SymbolIcon("checkmark.circle.fill", size: .row, color: AppAccent.primary)
|
||||||
.foregroundStyle(AppAccent.primary)
|
|
||||||
Text(String(localized: "\(habitCount) habits tracked"))
|
Text(String(localized: "\(habitCount) habits tracked"))
|
||||||
|
.font(Design.Typography.body)
|
||||||
.foregroundStyle(AppTextColors.secondary)
|
.foregroundStyle(AppTextColors.secondary)
|
||||||
}
|
}
|
||||||
.font(.subheadline)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.padding(Design.Spacing.large)
|
.padding(Design.Spacing.large)
|
||||||
@ -115,13 +111,13 @@ struct ArcRenewalSheet: View {
|
|||||||
private var durationSection: some View {
|
private var durationSection: some View {
|
||||||
VStack(alignment: .leading, spacing: Design.Spacing.medium) {
|
VStack(alignment: .leading, spacing: Design.Spacing.medium) {
|
||||||
Text(String(localized: "Next Arc Duration"))
|
Text(String(localized: "Next Arc Duration"))
|
||||||
.font(.headline)
|
.font(Design.Typography.headline)
|
||||||
.foregroundStyle(AppTextColors.primary)
|
.foregroundStyle(AppTextColors.primary)
|
||||||
|
|
||||||
VStack(spacing: Design.Spacing.small) {
|
VStack(spacing: Design.Spacing.small) {
|
||||||
HStack {
|
HStack {
|
||||||
Text(String(localized: "\(Int(durationDays)) days"))
|
Text(String(localized: "\(Int(durationDays)) days"))
|
||||||
.font(.title3.bold())
|
.font(Design.Typography.displaySmall)
|
||||||
.foregroundStyle(AppAccent.primary)
|
.foregroundStyle(AppAccent.primary)
|
||||||
Spacer()
|
Spacer()
|
||||||
}
|
}
|
||||||
@ -131,11 +127,11 @@ struct ArcRenewalSheet: View {
|
|||||||
|
|
||||||
HStack {
|
HStack {
|
||||||
Text(String(localized: "1 week"))
|
Text(String(localized: "1 week"))
|
||||||
.font(.caption)
|
.font(Design.Typography.caption)
|
||||||
.foregroundStyle(AppTextColors.tertiary)
|
.foregroundStyle(AppTextColors.tertiary)
|
||||||
Spacer()
|
Spacer()
|
||||||
Text(String(localized: "1 year"))
|
Text(String(localized: "1 year"))
|
||||||
.font(.caption)
|
.font(Design.Typography.caption)
|
||||||
.foregroundStyle(AppTextColors.tertiary)
|
.foregroundStyle(AppTextColors.tertiary)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -147,7 +143,7 @@ struct ArcRenewalSheet: View {
|
|||||||
durationDays = Double(days)
|
durationDays = Double(days)
|
||||||
} label: {
|
} label: {
|
||||||
Text("\(days)")
|
Text("\(days)")
|
||||||
.font(.caption.bold())
|
.font(Design.Typography.captionBold)
|
||||||
.foregroundStyle(Int(durationDays) == days ? AppTextColors.primary : AppTextColors.secondary)
|
.foregroundStyle(Int(durationDays) == days ? AppTextColors.primary : AppTextColors.secondary)
|
||||||
.padding(.horizontal, Design.Spacing.small)
|
.padding(.horizontal, Design.Spacing.small)
|
||||||
.padding(.vertical, Design.Spacing.xSmall)
|
.padding(.vertical, Design.Spacing.xSmall)
|
||||||
@ -171,10 +167,10 @@ struct ArcRenewalSheet: View {
|
|||||||
dismiss()
|
dismiss()
|
||||||
} label: {
|
} label: {
|
||||||
HStack {
|
HStack {
|
||||||
Image(systemName: "arrow.clockwise")
|
SymbolIcon("arrow.clockwise", size: .row, color: AppTextColors.primary)
|
||||||
Text(String(localized: "Continue with Same Habits"))
|
Text(String(localized: "Continue with Same Habits"))
|
||||||
}
|
}
|
||||||
.font(.headline)
|
.font(Design.Typography.headline)
|
||||||
.foregroundStyle(AppTextColors.primary)
|
.foregroundStyle(AppTextColors.primary)
|
||||||
.frame(maxWidth: .infinity)
|
.frame(maxWidth: .infinity)
|
||||||
.padding(Design.Spacing.medium)
|
.padding(Design.Spacing.medium)
|
||||||
@ -189,10 +185,10 @@ struct ArcRenewalSheet: View {
|
|||||||
showingEditSheet = true
|
showingEditSheet = true
|
||||||
} label: {
|
} label: {
|
||||||
HStack {
|
HStack {
|
||||||
Image(systemName: "pencil")
|
SymbolIcon("pencil", size: .row, color: AppAccent.primary)
|
||||||
Text(String(localized: "Continue with Changes"))
|
Text(String(localized: "Continue with Changes"))
|
||||||
}
|
}
|
||||||
.font(.headline)
|
.font(Design.Typography.headline)
|
||||||
.foregroundStyle(AppAccent.primary)
|
.foregroundStyle(AppAccent.primary)
|
||||||
.frame(maxWidth: .infinity)
|
.frame(maxWidth: .infinity)
|
||||||
.padding(Design.Spacing.medium)
|
.padding(Design.Spacing.medium)
|
||||||
@ -211,10 +207,10 @@ struct ArcRenewalSheet: View {
|
|||||||
dismiss()
|
dismiss()
|
||||||
} label: {
|
} label: {
|
||||||
HStack {
|
HStack {
|
||||||
Image(systemName: "checkmark.circle")
|
SymbolIcon("checkmark.circle", size: .row, color: AppTextColors.secondary)
|
||||||
Text(String(localized: "End This Ritual"))
|
Text(String(localized: "End This Ritual"))
|
||||||
}
|
}
|
||||||
.font(.subheadline)
|
.font(Design.Typography.body)
|
||||||
.foregroundStyle(AppTextColors.secondary)
|
.foregroundStyle(AppTextColors.secondary)
|
||||||
.frame(maxWidth: .infinity)
|
.frame(maxWidth: .infinity)
|
||||||
.padding(Design.Spacing.medium)
|
.padding(Design.Spacing.medium)
|
||||||
|
|||||||
@ -200,19 +200,17 @@ struct PresetDetailSheet: View {
|
|||||||
|
|
||||||
private var headerSection: some View {
|
private var headerSection: some View {
|
||||||
VStack(spacing: Design.Spacing.medium) {
|
VStack(spacing: Design.Spacing.medium) {
|
||||||
Image(systemName: preset.iconName)
|
SymbolIcon(preset.iconName, size: .hero, color: AppAccent.primary)
|
||||||
.font(.system(size: Design.IconSize.hero))
|
|
||||||
.foregroundStyle(AppAccent.primary)
|
|
||||||
|
|
||||||
Text(preset.theme)
|
Text(preset.theme)
|
||||||
.font(.title3)
|
.font(Design.Typography.bodyLarge)
|
||||||
.foregroundStyle(AppTextColors.secondary)
|
.foregroundStyle(AppTextColors.secondary)
|
||||||
|
|
||||||
HStack(spacing: Design.Spacing.large) {
|
HStack(spacing: Design.Spacing.large) {
|
||||||
Label(preset.timeOfDay.displayName, systemImage: preset.timeOfDay.symbolName)
|
Label(preset.timeOfDay.displayName, systemImage: preset.timeOfDay.symbolName)
|
||||||
Label(String(localized: "\(preset.durationDays) days"), systemImage: "calendar")
|
Label(String(localized: "\(preset.durationDays) days"), systemImage: "calendar")
|
||||||
}
|
}
|
||||||
.font(.caption)
|
.font(Design.Typography.caption)
|
||||||
.foregroundStyle(AppTextColors.tertiary)
|
.foregroundStyle(AppTextColors.tertiary)
|
||||||
}
|
}
|
||||||
.frame(maxWidth: .infinity)
|
.frame(maxWidth: .infinity)
|
||||||
|
|||||||
@ -29,20 +29,17 @@ struct RitualFocusCardView: View {
|
|||||||
VStack(alignment: .leading, spacing: Design.Spacing.medium) {
|
VStack(alignment: .leading, spacing: Design.Spacing.medium) {
|
||||||
HStack(spacing: Design.Spacing.small) {
|
HStack(spacing: Design.Spacing.small) {
|
||||||
// Icon
|
// Icon
|
||||||
Image(systemName: iconName)
|
SymbolIcon(iconName, size: .row, color: AppAccent.primary)
|
||||||
.foregroundStyle(AppAccent.primary)
|
|
||||||
.accessibilityHidden(true)
|
.accessibilityHidden(true)
|
||||||
|
|
||||||
// Title
|
// Title
|
||||||
Text(title)
|
TitleLabel(title, style: .headline, color: AppTextColors.primary)
|
||||||
.font(.headline)
|
|
||||||
.foregroundStyle(AppTextColors.primary)
|
|
||||||
|
|
||||||
Spacer(minLength: Design.Spacing.medium)
|
Spacer(minLength: Design.Spacing.medium)
|
||||||
|
|
||||||
// Day label
|
// Day label - needs additional modifiers (padding, background)
|
||||||
Text(dayLabel)
|
Text(dayLabel)
|
||||||
.font(.caption)
|
.font(Design.Typography.caption)
|
||||||
.foregroundStyle(AppTextColors.secondary)
|
.foregroundStyle(AppTextColors.secondary)
|
||||||
.padding(.horizontal, Design.Spacing.small)
|
.padding(.horizontal, Design.Spacing.small)
|
||||||
.padding(.vertical, Design.Spacing.xxxSmall)
|
.padding(.vertical, Design.Spacing.xxxSmall)
|
||||||
@ -51,16 +48,12 @@ struct RitualFocusCardView: View {
|
|||||||
.accessibilityLabel(Text(dayLabel))
|
.accessibilityLabel(Text(dayLabel))
|
||||||
}
|
}
|
||||||
|
|
||||||
Text(theme)
|
BodyLabel(theme, color: AppTextColors.secondary)
|
||||||
.font(.subheadline)
|
|
||||||
.foregroundStyle(AppTextColors.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)
|
||||||
Text(completionSummary)
|
CaptionLabel(completionSummary, color: AppTextColors.secondary)
|
||||||
.font(.caption)
|
|
||||||
.foregroundStyle(AppTextColors.secondary)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.padding(Design.Spacing.large)
|
.padding(Design.Spacing.large)
|
||||||
|
|||||||
@ -16,13 +16,11 @@ struct TodayEmptyStateView: View {
|
|||||||
|
|
||||||
VStack(spacing: Design.Spacing.large) {
|
VStack(spacing: Design.Spacing.large) {
|
||||||
// Icon
|
// Icon
|
||||||
Image(systemName: "sparkles")
|
SymbolIcon("sparkles", size: .hero, color: AppAccent.primary)
|
||||||
.font(.system(size: Design.IconSize.hero))
|
|
||||||
.foregroundStyle(AppAccent.primary)
|
|
||||||
.padding(.top, Design.Spacing.large)
|
.padding(.top, Design.Spacing.large)
|
||||||
|
|
||||||
Text(String(localized: "Rituals help you build consistent habits through focused, time-bound journeys."))
|
Text(String(localized: "Rituals help you build consistent habits through focused, time-bound journeys."))
|
||||||
.font(.subheadline)
|
.font(Design.Typography.body)
|
||||||
.foregroundStyle(AppTextColors.secondary)
|
.foregroundStyle(AppTextColors.secondary)
|
||||||
.multilineTextAlignment(.center)
|
.multilineTextAlignment(.center)
|
||||||
.padding(.horizontal, Design.Spacing.large)
|
.padding(.horizontal, Design.Spacing.large)
|
||||||
@ -36,7 +34,7 @@ struct TodayEmptyStateView: View {
|
|||||||
.fill(AppBorder.subtle)
|
.fill(AppBorder.subtle)
|
||||||
.frame(height: 1)
|
.frame(height: 1)
|
||||||
Text(String(localized: "or"))
|
Text(String(localized: "or"))
|
||||||
.font(.caption)
|
.font(Design.Typography.caption)
|
||||||
.foregroundStyle(AppTextColors.tertiary)
|
.foregroundStyle(AppTextColors.tertiary)
|
||||||
Rectangle()
|
Rectangle()
|
||||||
.fill(AppBorder.subtle)
|
.fill(AppBorder.subtle)
|
||||||
@ -73,7 +71,7 @@ struct TodayEmptyStateView: View {
|
|||||||
// Past rituals hint
|
// Past rituals hint
|
||||||
if !store.pastRituals.isEmpty {
|
if !store.pastRituals.isEmpty {
|
||||||
Text(String(localized: "You can also restart a past ritual from the Rituals tab."))
|
Text(String(localized: "You can also restart a past ritual from the Rituals tab."))
|
||||||
.font(.caption)
|
.font(Design.Typography.caption)
|
||||||
.foregroundStyle(AppTextColors.tertiary)
|
.foregroundStyle(AppTextColors.tertiary)
|
||||||
.multilineTextAlignment(.center)
|
.multilineTextAlignment(.center)
|
||||||
.padding(.top, Design.Spacing.small)
|
.padding(.top, Design.Spacing.small)
|
||||||
@ -97,8 +95,7 @@ struct TodayEmptyStateView: View {
|
|||||||
private var quickStartSection: some View {
|
private var quickStartSection: some View {
|
||||||
VStack(alignment: .leading, spacing: Design.Spacing.small) {
|
VStack(alignment: .leading, spacing: Design.Spacing.small) {
|
||||||
Text(String(localized: "Quick Start"))
|
Text(String(localized: "Quick Start"))
|
||||||
.font(.caption)
|
.font(Design.Typography.captionMedium)
|
||||||
.fontWeight(.medium)
|
|
||||||
.foregroundStyle(AppTextColors.tertiary)
|
.foregroundStyle(AppTextColors.tertiary)
|
||||||
.padding(.horizontal, Design.Spacing.medium)
|
.padding(.horizontal, Design.Spacing.medium)
|
||||||
|
|
||||||
@ -135,12 +132,10 @@ private struct QuickStartButton: View {
|
|||||||
var body: some View {
|
var body: some View {
|
||||||
Button(action: action) {
|
Button(action: action) {
|
||||||
HStack(spacing: Design.Spacing.small) {
|
HStack(spacing: Design.Spacing.small) {
|
||||||
Image(systemName: goal.symbolName)
|
SymbolIcon(goal.symbolName, size: .row, color: AppAccent.primary)
|
||||||
.font(.body)
|
|
||||||
.foregroundStyle(AppAccent.primary)
|
|
||||||
|
|
||||||
Text(goal.displayName)
|
Text(goal.displayName)
|
||||||
.font(.subheadline)
|
.font(Design.Typography.body)
|
||||||
.foregroundStyle(AppTextColors.primary)
|
.foregroundStyle(AppTextColors.primary)
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
|
|||||||
@ -25,22 +25,20 @@ struct TodayHabitRowView: View {
|
|||||||
var body: some View {
|
var body: some View {
|
||||||
Button(action: action) {
|
Button(action: action) {
|
||||||
HStack(spacing: Design.Spacing.medium) {
|
HStack(spacing: Design.Spacing.medium) {
|
||||||
Image(systemName: symbolName)
|
SymbolIcon(symbolName, size: .row, color: isCompleted ? AppStatus.success : AppAccent.primary)
|
||||||
.font(.body)
|
|
||||||
.foregroundStyle(isCompleted ? AppStatus.success : AppAccent.primary)
|
|
||||||
.frame(width: AppMetrics.Size.iconLarge)
|
.frame(width: AppMetrics.Size.iconLarge)
|
||||||
.accessibilityHidden(true)
|
.accessibilityHidden(true)
|
||||||
|
|
||||||
Text(title)
|
BodyLabel(title, color: AppTextColors.primary)
|
||||||
.font(.subheadline)
|
|
||||||
.foregroundStyle(AppTextColors.primary)
|
|
||||||
|
|
||||||
Spacer(minLength: Design.Spacing.medium)
|
Spacer(minLength: Design.Spacing.medium)
|
||||||
|
|
||||||
Image(systemName: isCompleted ? "checkmark.circle.fill" : "circle")
|
SymbolIcon(
|
||||||
.font(.body)
|
isCompleted ? "checkmark.circle.fill" : "circle",
|
||||||
.foregroundStyle(isCompleted ? AppStatus.success : AppBorder.subtle)
|
size: .row,
|
||||||
.accessibilityHidden(true)
|
color: isCompleted ? AppStatus.success : AppBorder.subtle
|
||||||
|
)
|
||||||
|
.accessibilityHidden(true)
|
||||||
}
|
}
|
||||||
.padding(.horizontal, horizontalPadding)
|
.padding(.horizontal, horizontalPadding)
|
||||||
.padding(.vertical, Design.Spacing.medium)
|
.padding(.vertical, Design.Spacing.medium)
|
||||||
|
|||||||
@ -10,13 +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) {
|
||||||
Text(String(localized: "Today"))
|
TitleLabel(String(localized: "Today"), style: .displayLarge, color: AppTextColors.primary)
|
||||||
.font(.largeTitle)
|
BodyLabel(dateText, color: AppTextColors.secondary)
|
||||||
.foregroundStyle(AppTextColors.primary)
|
|
||||||
.bold()
|
|
||||||
Text(dateText)
|
|
||||||
.font(.subheadline)
|
|
||||||
.foregroundStyle(AppTextColors.secondary)
|
|
||||||
}
|
}
|
||||||
.frame(maxWidth: .infinity, alignment: .leading)
|
.frame(maxWidth: .infinity, alignment: .leading)
|
||||||
.accessibilityElement(children: .combine)
|
.accessibilityElement(children: .combine)
|
||||||
|
|||||||
@ -48,19 +48,17 @@ struct TodayNoRitualsForTimeView: View {
|
|||||||
|
|
||||||
VStack(spacing: Design.Spacing.large) {
|
VStack(spacing: Design.Spacing.large) {
|
||||||
// Icon
|
// Icon
|
||||||
Image(systemName: currentTimePeriod.symbolName)
|
SymbolIcon(currentTimePeriod.symbolName, size: .hero, color: AppAccent.primary.opacity(0.6))
|
||||||
.font(.system(size: Design.IconSize.hero))
|
|
||||||
.foregroundStyle(AppAccent.primary.opacity(0.6))
|
|
||||||
.padding(.top, Design.Spacing.large)
|
.padding(.top, Design.Spacing.large)
|
||||||
|
|
||||||
VStack(spacing: Design.Spacing.xSmall) {
|
VStack(spacing: Design.Spacing.xSmall) {
|
||||||
Text(String(localized: "No rituals scheduled for \(currentTimePeriod.displayName.lowercased())."))
|
Text(String(localized: "No rituals scheduled for \(currentTimePeriod.displayName.lowercased())."))
|
||||||
.font(.subheadline)
|
.font(Design.Typography.body)
|
||||||
.foregroundStyle(AppTextColors.secondary)
|
.foregroundStyle(AppTextColors.secondary)
|
||||||
.multilineTextAlignment(.center)
|
.multilineTextAlignment(.center)
|
||||||
|
|
||||||
Text(currentTimePeriod.timeRange)
|
Text(currentTimePeriod.timeRange)
|
||||||
.font(.caption)
|
.font(Design.Typography.caption)
|
||||||
.foregroundStyle(AppTextColors.tertiary)
|
.foregroundStyle(AppTextColors.tertiary)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,23 +66,21 @@ struct TodayNoRitualsForTimeView: View {
|
|||||||
if !nextRituals.isEmpty {
|
if !nextRituals.isEmpty {
|
||||||
VStack(alignment: .leading, spacing: Design.Spacing.medium) {
|
VStack(alignment: .leading, spacing: Design.Spacing.medium) {
|
||||||
Text(String(localized: "Coming up later:"))
|
Text(String(localized: "Coming up later:"))
|
||||||
.font(.caption)
|
.font(Design.Typography.caption)
|
||||||
.foregroundStyle(AppTextColors.tertiary)
|
.foregroundStyle(AppTextColors.tertiary)
|
||||||
|
|
||||||
ForEach(nextRituals) { ritual in
|
ForEach(nextRituals) { ritual in
|
||||||
HStack(spacing: Design.Spacing.small) {
|
HStack(spacing: Design.Spacing.small) {
|
||||||
Image(systemName: ritual.timeOfDay.symbolName)
|
SymbolIcon(ritual.timeOfDay.symbolName, size: .chevron, color: AppTextColors.secondary)
|
||||||
.font(.caption)
|
|
||||||
.foregroundStyle(AppTextColors.secondary)
|
|
||||||
|
|
||||||
Text(ritual.title)
|
Text(ritual.title)
|
||||||
.font(.subheadline)
|
.font(Design.Typography.body)
|
||||||
.foregroundStyle(AppTextColors.primary)
|
.foregroundStyle(AppTextColors.primary)
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
|
|
||||||
Text(ritual.timeOfDay.displayName)
|
Text(ritual.timeOfDay.displayName)
|
||||||
.font(.caption)
|
.font(Design.Typography.caption)
|
||||||
.foregroundStyle(AppTextColors.tertiary)
|
.foregroundStyle(AppTextColors.tertiary)
|
||||||
}
|
}
|
||||||
.padding(Design.Spacing.small)
|
.padding(Design.Spacing.small)
|
||||||
@ -100,7 +96,7 @@ struct TodayNoRitualsForTimeView: View {
|
|||||||
tomorrowRitual.timeOfDay.displayName,
|
tomorrowRitual.timeOfDay.displayName,
|
||||||
tomorrowRitual.timeOfDay.timeRange
|
tomorrowRitual.timeOfDay.timeRange
|
||||||
))
|
))
|
||||||
.font(.caption)
|
.font(Design.Typography.caption)
|
||||||
.foregroundStyle(AppTextColors.tertiary)
|
.foregroundStyle(AppTextColors.tertiary)
|
||||||
.multilineTextAlignment(.center)
|
.multilineTextAlignment(.center)
|
||||||
.padding(.top, Design.Spacing.small)
|
.padding(.top, Design.Spacing.small)
|
||||||
@ -108,7 +104,7 @@ struct TodayNoRitualsForTimeView: View {
|
|||||||
|
|
||||||
// Motivational message
|
// Motivational message
|
||||||
Text(String(localized: "Enjoy this moment. Your next ritual will appear when it's time."))
|
Text(String(localized: "Enjoy this moment. Your next ritual will appear when it's time."))
|
||||||
.font(.caption)
|
.font(Design.Typography.caption)
|
||||||
.foregroundStyle(AppTextColors.tertiary)
|
.foregroundStyle(AppTextColors.tertiary)
|
||||||
.multilineTextAlignment(.center)
|
.multilineTextAlignment(.center)
|
||||||
.padding(.top, Design.Spacing.small)
|
.padding(.top, Design.Spacing.small)
|
||||||
|
|||||||
@ -33,8 +33,7 @@ struct TodayRitualSectionView: View {
|
|||||||
Spacer()
|
Spacer()
|
||||||
|
|
||||||
// Time of day indicator
|
// Time of day indicator
|
||||||
Image(systemName: timeOfDay.symbolName)
|
SymbolIcon(timeOfDay.symbolName, size: .row, color: AppTextColors.tertiary)
|
||||||
.foregroundStyle(AppTextColors.tertiary)
|
|
||||||
.accessibilityLabel(timeOfDay.displayName)
|
.accessibilityLabel(timeOfDay.displayName)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user