feat: Update text color to improve readability across multiple authentication views

This commit is contained in:
2026-02-28 13:21:24 +05:00
parent 7272f24595
commit d1fcc04125
9 changed files with 379 additions and 107 deletions

View File

@@ -0,0 +1,81 @@
import SwiftUI
// MARK: - Glass Modifier (5-layer glass that works on black)
//
// Layer stack:
// 1. .ultraThinMaterial system blur
// 2. black.opacity(0.22) dark tint (depth on dark mode)
// 3. whiteclear gradient highlight / light refraction, blendMode(.screen)
// 4. double stroke outer weak + inner stronger = glass edge
// 5. shadow depth
struct GlassModifier: ViewModifier {
let cornerRadius: CGFloat
func body(content: Content) -> some View {
let shape = RoundedRectangle(cornerRadius: cornerRadius, style: .continuous)
if #available(iOS 26, *) {
content
.background {
shape.fill(.clear)
.glassEffect(.regular, in: .rect(cornerRadius: cornerRadius))
}
} else {
content
.background {
ZStack {
shape.fill(.ultraThinMaterial)
shape.fill(Color.black.opacity(0.22))
shape.fill(
LinearGradient(
colors: [Color.white.opacity(0.14), .clear],
startPoint: .top,
endPoint: .bottom
)
).blendMode(.screen)
shape.stroke(Color.white.opacity(0.10), lineWidth: 1)
shape.stroke(Color.white.opacity(0.18), lineWidth: 1).padding(1.5)
}
.shadow(color: Color.black.opacity(0.45), radius: 22, y: 14)
}
}
}
}
// MARK: - View Extension
extension View {
/// 5-layer frosted glass background.
func glass(cornerRadius: CGFloat = 24) -> some View {
modifier(GlassModifier(cornerRadius: cornerRadius))
}
/// Glass capsule convenience for pill-shaped elements.
@ViewBuilder
func glassCapsule() -> some View {
if #available(iOS 26, *) {
background {
Capsule().fill(.clear)
.glassEffect(.regular, in: .capsule)
}
} else {
background {
ZStack {
Capsule().fill(.ultraThinMaterial)
Capsule().fill(Color.black.opacity(0.22))
Capsule().fill(
LinearGradient(
colors: [Color.white.opacity(0.14), .clear],
startPoint: .top,
endPoint: .bottom
)
).blendMode(.screen)
Capsule().stroke(Color.white.opacity(0.10), lineWidth: 1)
Capsule().stroke(Color.white.opacity(0.18), lineWidth: 1).padding(1.5)
}
.shadow(color: Color.black.opacity(0.45), radius: 22, y: 14)
}
}
}
}

View File

@@ -1,9 +1,24 @@
import SwiftUI import SwiftUI
import UIKit import UIKit
// MARK: - Glass Effect ID Modifier (iOS 26+)
private struct GlassEffectIDModifier: ViewModifier {
let id: String
let namespace: Namespace.ID?
nonisolated func body(content: Content) -> some View {
if #available(iOS 26, *), let namespace {
content.glassEffectID(id, in: namespace)
} else {
content
}
}
}
// MARK: - Tab // MARK: - Tab
enum RosettaTab: CaseIterable { enum RosettaTab: CaseIterable, Sendable {
case chats case chats
case settings case settings
case search case search
@@ -41,26 +56,33 @@ struct TabBadge {
} }
// MARK: - RosettaTabBar // MARK: - RosettaTabBar
/// Figma spec:
/// Container: padding(25h, 16t, 25b), gap=8
/// Main pill: 282x62, r=296, padding(4h, 3v), glass+shadow
/// Each tab: 99x56, icon 30pt, label 10pt
/// Selected: #EDEDED rect r=100, icon+label #008BFF, label bold
/// Unselected: icon+label #404040
/// Search pill: 62x62, glass+shadow, icon 17pt #404040
struct RosettaTabBar: View { struct RosettaTabBar: View {
let selectedTab: RosettaTab let selectedTab: RosettaTab
var onTabSelected: ((RosettaTab) -> Void)? var onTabSelected: ((RosettaTab) -> Void)?
var badges: [TabBadge] = [] var badges: [TabBadge] = []
@Namespace private var glassNS
var body: some View { var body: some View {
if #available(iOS 26, *) {
GlassEffectContainer(spacing: 8) {
tabBarContent
}
.padding(.horizontal, 25)
.padding(.top, 4)
} else {
tabBarContent
.padding(.horizontal, 25)
.padding(.top, 4)
}
}
private var tabBarContent: some View {
HStack(spacing: 8) { HStack(spacing: 8) {
mainTabsPill mainTabsPill
searchPill searchPill
} }
.padding(.horizontal, 25)
.padding(.top, 4)
} }
} }
@@ -68,145 +90,314 @@ struct RosettaTabBar: View {
private extension RosettaTabBar { private extension RosettaTabBar {
var mainTabsPill: some View { var mainTabsPill: some View {
// Content on top NOT clipped (lens can pop out)
HStack(spacing: 0) { HStack(spacing: 0) {
ForEach(RosettaTab.allCases.filter { $0 != .search }, id: \.self) { tab in ForEach(RosettaTab.allCases.filter { $0 != .search }, id: \.self) { tab in
tabItem(tab) TabItemButton(
tab: tab,
isSelected: tab == selectedTab,
badgeText: badges.first(where: { $0.tab == tab })?.text,
onTap: { onTabSelected?(tab) },
glassNamespace: glassNS
)
} }
} }
.padding(.horizontal, 4) .padding(.horizontal, 4)
.padding(.top, 3) .padding(.top, 3)
.padding(.bottom, 3) .padding(.bottom, 3)
.frame(height: 62) .frame(height: 62)
.applyGlassPill() // Background clipped separately content stays unclipped
.background {
mainPillGlass
}
} }
func tabItem(_ tab: RosettaTab) -> some View { @ViewBuilder
let isSelected = tab == selectedTab var mainPillGlass: some View {
let badgeText = badges.first(where: { $0.tab == tab })?.text if #available(iOS 26, *) {
Capsule().fill(.clear).glassEffect(.regular, in: .capsule)
return Button { } else {
withAnimation(.spring(response: 0.3, dampingFraction: 0.8)) { ZStack {
onTabSelected?(tab) // 1. Material
Capsule().fill(.ultraThinMaterial)
// 2. Dark tint
Capsule().fill(Color.black.opacity(0.22))
// 3. Highlight
Capsule().fill(
LinearGradient(
colors: [Color.white.opacity(0.14), .clear],
startPoint: .top,
endPoint: .bottom
)
).blendMode(.screen)
// 4a. Outer stroke
Capsule().stroke(Color.white.opacity(0.10), lineWidth: 1)
// 4b. Inner stroke
Capsule().stroke(Color.white.opacity(0.18), lineWidth: 1).padding(1.5)
} }
} label: { // 5. Shadows
.shadow(color: Color.black.opacity(0.45), radius: 22, y: 14)
}
}
}
// MARK: - Tab Item Button
private struct TabItemButton: View {
let tab: RosettaTab
let isSelected: Bool
let badgeText: String?
let onTap: () -> Void
var glassNamespace: Namespace.ID?
@State private var pressed = false
var body: some View {
Button(action: onTap) {
VStack(spacing: 1) { VStack(spacing: 1) {
ZStack(alignment: .topTrailing) { ZStack(alignment: .topTrailing) {
Image(systemName: isSelected ? tab.selectedIcon : tab.icon) Image(systemName: isSelected ? tab.selectedIcon : tab.icon)
.font(.system(size: 22)) .font(.system(size: 22))
.foregroundStyle(isSelected ? RosettaColors.primaryBlue : RosettaColors.adaptive(light: Color(hex: 0x404040), dark: Color(hex: 0x8E8E93))) .foregroundStyle(tabColor)
.frame(height: 30) .frame(height: 30)
if let badgeText { if let badgeText {
badgeView(badgeText) Text(badgeText)
.font(.system(size: 10, weight: .medium))
.foregroundStyle(.white)
.padding(.horizontal, badgeText.count > 2 ? 4 : 0)
.frame(minWidth: 18, minHeight: 18)
.background(Capsule().fill(RosettaColors.error))
.offset(x: 10, y: -4)
} }
} }
Text(tab.label) Text(tab.label)
.font(.system(size: 10, weight: isSelected ? .bold : .medium)) .font(.system(size: 10, weight: isSelected ? .bold : .medium))
.foregroundStyle(isSelected ? RosettaColors.primaryBlue : RosettaColors.adaptive(light: Color(hex: 0x404040), dark: Color(hex: 0x8E8E93))) .foregroundStyle(tabColor)
} }
.padding(.horizontal, 8)
.padding(.top, 6)
.padding(.bottom, 7)
.frame(maxWidth: .infinity) .frame(maxWidth: .infinity)
.background { .background {
if isSelected { if isSelected && !pressed {
RoundedRectangle(cornerRadius: 100) RoundedRectangle(cornerRadius: 100)
.fill(RosettaColors.adaptive( .fill(RosettaColors.adaptive(
light: Color(hex: 0xEDEDED), light: Color(hex: 0xEDEDED),
dark: Color.white.opacity(0.12) dark: Color.white.opacity(0.12)
)) ))
.padding(.horizontal, -8)
.padding(.vertical, -6)
} }
} }
.contentShape(Rectangle())
} }
.buttonStyle(.plain) .buttonStyle(.plain)
// Lens: padding glass bubble scale lift
.padding(14)
.background {
if pressed {
lensBubble
.transition(.scale(scale: 0.8).combined(with: .opacity))
}
}
.scaleEffect(pressed ? 1.12 : 1)
.offset(y: pressed ? -28 : 0)
.shadow(color: .black.opacity(pressed ? 0.45 : 0), radius: 22, y: 14)
.shadow(color: Color.cyan.opacity(pressed ? 0.12 : 0), radius: 20, y: 0)
.animation(.spring(response: 0.34, dampingFraction: 0.65), value: pressed)
.simultaneousGesture(
DragGesture(minimumDistance: 0)
.onChanged { _ in
if !pressed {
pressed = true
UIImpactFeedbackGenerator(style: .light).impactOccurred()
}
}
.onEnded { _ in pressed = false }
)
.modifier(GlassEffectIDModifier(id: "\(tab)", namespace: glassNamespace))
.accessibilityLabel(tab.label) .accessibilityLabel(tab.label)
.accessibilityAddTraits(isSelected ? .isSelected : []) .accessibilityAddTraits(isSelected ? .isSelected : [])
} }
private var tabColor: Color {
isSelected
? RosettaColors.primaryBlue
: RosettaColors.adaptive(
light: Color(hex: 0x404040),
dark: Color(hex: 0x8E8E93)
)
}
// MARK: Lens Bubble
@ViewBuilder
private var lensBubble: some View {
if #available(iOS 26, *) {
Circle()
.fill(.clear)
.glassEffect(.regular.interactive(), in: .circle)
} else {
ZStack {
// 1. Material
Circle().fill(.ultraThinMaterial)
// 2. Dark tint
Circle().fill(Color.black.opacity(0.22))
// 3. Highlight (topbottom, screen blend)
Circle().fill(
LinearGradient(
colors: [Color.white.opacity(0.14), .clear],
startPoint: .topLeading,
endPoint: .bottomTrailing
)
).blendMode(.screen)
// 4a. Outer stroke
Circle().stroke(Color.white.opacity(0.10), lineWidth: 1)
// 4b. Inner stroke
Circle().stroke(Color.white.opacity(0.18), lineWidth: 1).padding(1.5)
// 6. Rainbow (thin, subtle, screen blend)
Circle().stroke(
AngularGradient(
colors: [
Color.cyan.opacity(0.55),
Color.blue.opacity(0.55),
Color.purple.opacity(0.55),
Color.pink.opacity(0.55),
Color.orange.opacity(0.55),
Color.yellow.opacity(0.45),
Color.cyan.opacity(0.55),
],
center: .center
),
lineWidth: 1.4
).blendMode(.screen)
}
}
}
} }
// MARK: - Search Pill // MARK: - Search Pill
private extension RosettaTabBar { private extension RosettaTabBar {
var searchPill: some View { var searchPill: some View {
let isSelected = selectedTab == .search SearchPillButton(
isSelected: selectedTab == .search,
onTap: { onTabSelected?(.search) },
glassNamespace: glassNS
)
}
}
return Button { private struct SearchPillButton: View {
withAnimation(.spring(response: 0.3, dampingFraction: 0.8)) { let isSelected: Bool
onTabSelected?(.search) let onTap: () -> Void
} var glassNamespace: Namespace.ID?
} label: {
Image(systemName: isSelected ? "magnifyingglass" : "magnifyingglass") @State private var pressed = false
var body: some View {
Button(action: onTap) {
Image(systemName: "magnifyingglass")
.font(.system(size: 17, weight: .semibold)) .font(.system(size: 17, weight: .semibold))
.foregroundStyle(isSelected ? RosettaColors.primaryBlue : RosettaColors.adaptive(light: Color(hex: 0x404040), dark: Color(hex: 0x8E8E93))) .foregroundStyle(
.frame(width: 54, height: 54) isSelected
.background { ? RosettaColors.primaryBlue
if isSelected { : RosettaColors.adaptive(
Circle() light: Color(hex: 0x404040),
.fill(RosettaColors.adaptive( dark: Color(hex: 0x8E8E93)
light: Color(hex: 0xEDEDED), )
dark: Color.white.opacity(0.12) )
))
}
}
} }
.buttonStyle(.plain) .buttonStyle(.plain)
.padding(4) // Lens
.padding(14)
.background {
if pressed {
searchLensBubble
.transition(.scale(scale: 0.8).combined(with: .opacity))
}
}
.scaleEffect(pressed ? 1.15 : 1)
.offset(y: pressed ? -28 : 0)
.shadow(color: .black.opacity(pressed ? 0.45 : 0), radius: 22, y: 14)
.shadow(color: Color.cyan.opacity(pressed ? 0.12 : 0), radius: 20, y: 0)
.animation(.spring(response: 0.34, dampingFraction: 0.65), value: pressed)
.simultaneousGesture(
DragGesture(minimumDistance: 0)
.onChanged { _ in
if !pressed {
pressed = true
UIImpactFeedbackGenerator(style: .light).impactOccurred()
}
}
.onEnded { _ in pressed = false }
)
.frame(width: 62, height: 62) .frame(width: 62, height: 62)
.applyGlassPill() // Background clipped separately
.background { searchPillGlass }
.modifier(GlassEffectIDModifier(id: "search", namespace: glassNamespace))
.accessibilityLabel("Search") .accessibilityLabel("Search")
.accessibilityAddTraits(isSelected ? .isSelected : []) .accessibilityAddTraits(isSelected ? .isSelected : [])
} }
}
// MARK: - Glass Pill // MARK: Lens for search
private struct GlassPillModifier: ViewModifier { @ViewBuilder
func body(content: Content) -> some View { private var searchLensBubble: some View {
if #available(iOS 26, *) { if #available(iOS 26, *) {
content Circle()
.glassEffect(.regular, in: .capsule) .fill(.clear)
.glassEffect(.regular.interactive(), in: .circle)
} else { } else {
content ZStack {
.background( Circle().fill(.ultraThinMaterial)
Capsule() Circle().fill(Color.black.opacity(0.22))
.fill(RosettaColors.adaptive( Circle().fill(
light: Color.white.opacity(0.65), LinearGradient(
dark: Color(hex: 0x2A2A2A).opacity(0.8) colors: [Color.white.opacity(0.14), .clear],
)) startPoint: .topLeading,
.shadow(color: RosettaColors.adaptive( endPoint: .bottomTrailing
light: Color(hex: 0xDDDDDD).opacity(0.5),
dark: Color.black.opacity(0.3)
), radius: 16, y: 4)
) )
).blendMode(.screen)
Circle().stroke(Color.white.opacity(0.10), lineWidth: 1)
Circle().stroke(Color.white.opacity(0.18), lineWidth: 1).padding(1.5)
Circle().stroke(
AngularGradient(
colors: [
Color.cyan.opacity(0.55),
Color.blue.opacity(0.55),
Color.purple.opacity(0.55),
Color.pink.opacity(0.55),
Color.orange.opacity(0.55),
Color.yellow.opacity(0.45),
Color.cyan.opacity(0.55),
],
center: .center
),
lineWidth: 1.4
).blendMode(.screen)
} }
} }
}
private extension View {
func applyGlassPill() -> some View {
modifier(GlassPillModifier())
}
}
// MARK: - Helpers
private extension RosettaTabBar {
func badgeView(_ text: String) -> some View {
Text(text)
.font(.system(size: 10, weight: .medium))
.foregroundStyle(.white)
.padding(.horizontal, text.count > 2 ? 4 : 0)
.frame(minWidth: 18, minHeight: 18)
.background(Capsule().fill(RosettaColors.error))
.offset(x: 10, y: -4)
} }
var safeAreaBottom: CGFloat { @ViewBuilder
guard let scene = UIApplication.shared.connectedScenes.first as? UIWindowScene, private var searchPillGlass: some View {
let window = scene.windows.first(where: \.isKeyWindow) else { return 0 } if #available(iOS 26, *) {
return window.safeAreaInsets.bottom Circle().fill(.clear).glassEffect(.regular, in: .circle)
} else {
ZStack {
Circle().fill(.ultraThinMaterial)
Circle().fill(Color.black.opacity(0.22))
Circle().fill(
LinearGradient(
colors: [Color.white.opacity(0.14), .clear],
startPoint: .top,
endPoint: .bottom
)
).blendMode(.screen)
Circle().stroke(Color.white.opacity(0.10), lineWidth: 1)
Circle().stroke(Color.white.opacity(0.18), lineWidth: 1).padding(1.5)
}
.shadow(color: Color.black.opacity(0.45), radius: 22, y: 14)
}
} }
} }
@@ -214,12 +405,12 @@ private extension RosettaTabBar {
#Preview { #Preview {
ZStack(alignment: .bottom) { ZStack(alignment: .bottom) {
RosettaColors.Adaptive.background.ignoresSafeArea() Color.black.ignoresSafeArea()
VStack { VStack {
Spacer() Spacer()
Text("Content here") Text("Hold a tab to see the lens")
.foregroundStyle(RosettaColors.Adaptive.text) .foregroundStyle(.white.opacity(0.5))
Spacer() Spacer()
} }

View File

@@ -58,7 +58,7 @@ private extension ConfirmSeedPhraseView {
Text("Enter words #2, #5, #9, #12 to confirm\nyou've backed up your phrase.") Text("Enter words #2, #5, #9, #12 to confirm\nyou've backed up your phrase.")
.font(.system(size: 15)) .font(.system(size: 15))
.foregroundStyle(RosettaColors.secondaryText) .foregroundStyle(Color.white.opacity(0.7))
.multilineTextAlignment(.center) .multilineTextAlignment(.center)
.lineSpacing(3) .lineSpacing(3)
} }

View File

@@ -51,7 +51,7 @@ private extension ImportSeedPhraseView {
Text("Enter your 12-word recovery phrase\nto restore your account.") Text("Enter your 12-word recovery phrase\nto restore your account.")
.font(.system(size: 15)) .font(.system(size: 15))
.foregroundStyle(RosettaColors.secondaryText) .foregroundStyle(Color.white.opacity(0.7))
.multilineTextAlignment(.center) .multilineTextAlignment(.center)
.lineSpacing(3) .lineSpacing(3)
} }

View File

@@ -107,7 +107,7 @@ struct WeakPasswordWarning: View {
Text("Your password is too weak. Consider using at least 6 characters for better security.") Text("Your password is too weak. Consider using at least 6 characters for better security.")
.font(.system(size: 13)) .font(.system(size: 13))
.foregroundStyle(RosettaColors.secondaryText) .foregroundStyle(Color.white.opacity(0.7))
.lineSpacing(2) .lineSpacing(2)
} }
.padding(14) .padding(14)

View File

@@ -54,7 +54,7 @@ private extension SeedPhraseView {
Text("Write down these 12 words in order.\nYou'll need them to restore your account.") Text("Write down these 12 words in order.\nYou'll need them to restore your account.")
.font(.system(size: 15)) .font(.system(size: 15))
.foregroundStyle(RosettaColors.secondaryText) .foregroundStyle(Color.white.opacity(0.7))
.multilineTextAlignment(.center) .multilineTextAlignment(.center)
.lineSpacing(3) .lineSpacing(3)
.opacity(isContentVisible ? 1.0 : 0.0) .opacity(isContentVisible ? 1.0 : 0.0)

View File

@@ -103,7 +103,7 @@ private extension SetPasswordView {
? "Set a password to protect your recovered account.\nYou'll need it to unlock Rosetta." ? "Set a password to protect your recovered account.\nYou'll need it to unlock Rosetta."
: "This password encrypts your keys locally.\nYou'll need it to unlock Rosetta.") : "This password encrypts your keys locally.\nYou'll need it to unlock Rosetta.")
.font(.system(size: 14)) .font(.system(size: 14))
.foregroundStyle(RosettaColors.secondaryText) .foregroundStyle(Color.white.opacity(0.7))
.multilineTextAlignment(.center) .multilineTextAlignment(.center)
.lineSpacing(2) .lineSpacing(2)
} }
@@ -175,7 +175,7 @@ private extension SetPasswordView {
Image(systemName: isRevealed ? "eye.slash" : "eye") Image(systemName: isRevealed ? "eye.slash" : "eye")
.font(.system(size: 16)) .font(.system(size: 16))
.foregroundStyle(RosettaColors.secondaryText) .foregroundStyle(Color.white.opacity(0.5))
.frame(width: 30, height: 30) .frame(width: 30, height: 30)
.contentShape(Rectangle()) .contentShape(Rectangle())
.onTapGesture { .onTapGesture {
@@ -218,7 +218,7 @@ private extension SetPasswordView {
Text("Your password is never stored or sent anywhere. It's only used to encrypt your keys locally.") Text("Your password is never stored or sent anywhere. It's only used to encrypt your keys locally.")
.font(.system(size: 13)) .font(.system(size: 13))
.foregroundStyle(RosettaColors.secondaryText) .foregroundStyle(Color.white.opacity(0.7))
.lineSpacing(2) .lineSpacing(2)
} }
.padding(16) .padding(16)

View File

@@ -79,7 +79,7 @@ struct UnlockView: View {
// Subtitle matching Android // Subtitle matching Android
Text("For unlock account enter password") Text("For unlock account enter password")
.font(.system(size: 15)) .font(.system(size: 15))
.foregroundStyle(RosettaColors.secondaryText) .foregroundStyle(Color.white.opacity(0.7))
.opacity(showSubtitle ? 1 : 0) .opacity(showSubtitle ? 1 : 0)
.offset(y: showSubtitle ? 0 : 8) .offset(y: showSubtitle ? 0 : 8)
@@ -136,7 +136,7 @@ private extension UnlockView {
Image(systemName: showPassword ? "eye.slash" : "eye") Image(systemName: showPassword ? "eye.slash" : "eye")
.font(.system(size: 18)) .font(.system(size: 18))
.foregroundStyle(Color(white: 0.45)) .foregroundStyle(Color.white.opacity(0.5))
.contentShape(Rectangle()) .contentShape(Rectangle())
.onTapGesture { showPassword.toggle() } .onTapGesture { showPassword.toggle() }
} }
@@ -195,7 +195,7 @@ private extension UnlockView {
VStack(spacing: 4) { VStack(spacing: 4) {
HStack(spacing: 0) { HStack(spacing: 0) {
Text("You can also ") Text("You can also ")
.foregroundStyle(RosettaColors.secondaryText) .foregroundStyle(Color.white.opacity(0.7))
Button { Button {
onCreateNewAccount?() onCreateNewAccount?()
@@ -207,13 +207,13 @@ private extension UnlockView {
.buttonStyle(.plain) .buttonStyle(.plain)
Text(" or") Text(" or")
.foregroundStyle(RosettaColors.secondaryText) .foregroundStyle(Color.white.opacity(0.7))
} }
.font(.system(size: 15)) .font(.system(size: 15))
HStack(spacing: 0) { HStack(spacing: 0) {
Text("create a ") Text("create a ")
.foregroundStyle(RosettaColors.secondaryText) .foregroundStyle(Color.white.opacity(0.7))
Button { Button {
onCreateNewAccount?() onCreateNewAccount?()

View File

@@ -90,7 +90,7 @@ private extension WelcomeView {
var subtitleSection: some View { var subtitleSection: some View {
Text("Secure messaging with\ncryptographic keys") Text("Secure messaging with\ncryptographic keys")
.font(.system(size: 16)) .font(.system(size: 16))
.foregroundStyle(RosettaColors.secondaryText) .foregroundStyle(Color.white.opacity(0.7))
.multilineTextAlignment(.center) .multilineTextAlignment(.center)
.opacity(isVisible ? 1.0 : 0.0) .opacity(isVisible ? 1.0 : 0.0)
.offset(y: isVisible ? 0 : 12) .offset(y: isVisible ? 0 : 12)
@@ -122,7 +122,7 @@ private extension WelcomeView {
Text(label) Text(label)
.font(.system(size: 13, weight: .medium)) .font(.system(size: 13, weight: .medium))
.foregroundStyle(RosettaColors.secondaryText) .foregroundStyle(Color.white.opacity(0.7))
} }
.accessibilityElement(children: .combine) .accessibilityElement(children: .combine)
.accessibilityLabel(label) .accessibilityLabel(label)